Calendar: Difference between revisions
revised/clarified task & added Template:Needs-review. Also updated the ALGOL 68 code to match. BTW: μέγας κῦδος to the Tcl code for the "octubre 1582" :Europe/Madrid es_ES calendar!!! |
→{{header|J}}: Updated example use to match changed requirements |
||
Line 165: | Line 165: | ||
</pre> |
</pre> |
||
=={{header|J}}== |
=={{header|J}}== |
||
{{Template:Needs-review}} |
|||
'''Solution:''' |
'''Solution:''' |
||
<lang j>require 'dates format' NB. J6.x |
<lang j>require 'dates format' NB. J6.x |
||
Line 173: | Line 172: | ||
formatCalendar=: calTitle , calBody</lang> |
formatCalendar=: calTitle , calBody</lang> |
||
'''Example use:''' |
'''Example use:''' |
||
<lang j> |
<lang j> 80 formatCalendar 1969 |
||
[Insert Snoopy here] |
|||
1969 |
|||
Jan │ Feb │ Mar |
Jan │ Feb │ Mar |
||
Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa |
|||
1 2 3 4│ 1│ |
1 2 3 4│ 1│ 1 |
||
5 6 7 8 9 10 11│ 2 3 4 5 6 7 8│ 2 3 4 5 |
5 6 7 8 9 10 11│ 2 3 4 5 6 7 8│ 2 3 4 5 6 7 8 |
||
12 13 14 15 16 17 18│ 9 10 11 12 13 14 15│ 9 10 11 12 |
12 13 14 15 16 17 18│ 9 10 11 12 13 14 15│ 9 10 11 12 13 14 15 |
||
19 20 21 22 23 24 25│ 16 17 18 19 20 21 22│ 16 17 18 19 |
19 20 21 22 23 24 25│ 16 17 18 19 20 21 22│ 16 17 18 19 20 21 22 |
||
26 27 28 29 30 31 │ 23 24 25 26 27 28 │ 23 24 25 26 |
26 27 28 29 30 31 │ 23 24 25 26 27 28 │ 23 24 25 26 27 28 29 |
||
│ │ 30 31 |
│ │ 30 31 |
||
─────────────────────┼─────────────────────┼───────────────────── |
|||
─────────────────────┼─────────────────────┼─────────────────────┼─────────────────────┼─────────────────────┼───────────────────── |
|||
Apr │ May │ Jun |
|||
Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa |
|||
1 2 3 4 5│ |
1 2 3 4 5│ 1 2 3│ 1 2 3 4 5 6 7 |
||
6 7 8 9 10 11 12│ |
6 7 8 9 10 11 12│ 4 5 6 7 8 9 10│ 8 9 10 11 12 13 14 |
||
13 14 15 16 17 18 19│ |
13 14 15 16 17 18 19│ 11 12 13 14 15 16 17│ 15 16 17 18 19 20 21 |
||
20 21 22 23 24 25 26│ |
20 21 22 23 24 25 26│ 18 19 20 21 22 23 24│ 22 23 24 25 26 27 28 |
||
27 28 29 30 |
27 28 29 30 │ 25 26 27 28 29 30 31│ 29 30 |
||
│ |
│ │ |
||
─────────────────────┼─────────────────────┼───────────────────── |
|||
Jul │ Aug │ Sep |
|||
Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa |
|||
1 2 3 4 5│ 1 2│ 1 2 3 4 5 6 |
|||
6 7 8 9 10 11 12│ 3 4 5 6 7 8 9│ 7 8 9 10 11 12 13 |
|||
13 14 15 16 17 18 19│ 10 11 12 13 14 15 16│ 14 15 16 17 18 19 20 |
|||
20 21 22 23 24 25 26│ 17 18 19 20 21 22 23│ 21 22 23 24 25 26 27 |
|||
27 28 29 30 31 │ 24 25 26 27 28 29 30│ 28 29 30 |
|||
│ 31 │ |
|||
─────────────────────┼─────────────────────┼───────────────────── |
|||
Oct │ Nov │ Dec |
|||
Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa |
|||
1 2 3 4│ 1│ 1 2 3 4 5 6 |
|||
5 6 7 8 9 10 11│ 2 3 4 5 6 7 8│ 7 8 9 10 11 12 13 |
|||
12 13 14 15 16 17 18│ 9 10 11 12 13 14 15│ 14 15 16 17 18 19 20 |
|||
19 20 21 22 23 24 25│ 16 17 18 19 20 21 22│ 21 22 23 24 25 26 27 |
|||
26 27 28 29 30 31 │ 23 24 25 26 27 28 29│ 28 29 30 31 |
|||
│ 30 │ </lang> |
|||
=={{header|PicoLisp}}== |
=={{header|PicoLisp}}== |
Revision as of 01:14, 12 June 2011
You are encouraged to solve this task according to the task description, using any language you may know.
Create a routine that will generate an text calendar for any date. Test the calendar by generating a calendar for the year 1969 on a IBM 3278 model 4 terminal (80×43 display with accented characters) of the time.
As a test case, target formatting the months of the year to fit nicely across the 80 character width page. Restrict number of lines in test output to 43.
(Ideally the program will generate well formatted calendars for any page width from 20 characters up)
Kudos (κῦδος) for routines that also correctly transition from Julian to Gregorian calendar in September 1752.
This task is inspired by Real Programmers Don't Use PASCAL by Ed Post, Datamation, volume 29 number 7, July 1983.
THE REAL PROGRAMMER'S NATURAL HABITAT "Taped to the wall is a line-printer Snoopy calender for the year 1969."
For further Kudos see task CALENDAR, for printing on a 132 character width
This page uses content from Wikipedia. The original article was at IBM 1403. The list of authors can be seen in the page history. As with Rosetta Code, the text of Wikipedia is available under the GNU FDL. (See links for details on variance) |
printer. Where all code and output is to be in UPPERCASE.
For economy of size, do not actually include Snoopy generation in either the code or the output, instead just output a place-holder.
ALGOL 68
<lang algol68>#!/usr/local/bin/a68g --script #
PROC print calendar = (INT year, page width)VOID: (
[]STRING month names = ( "January","February","March","April","May","June", "July","August","September","October","November","December"), weekday names = ("Su","Mo","Tu","We","Th","Fr","Sa"); FORMAT weekday fmt = $g,n(UPB weekday names - LWB weekday names)(" "g)$;
# Juggle the calendar format to fit the printer/screen width # INT day width = UPB weekday names[1], day gap=1; INT month width = (day width+day gap) * UPB weekday names-1; INT month heading lines = 2; INT month lines = (31 OVER UPB weekday names+month heading lines+2); # +2 for head/tail weeks # INT year cols = (page width+1) OVER (month width+1); INT year rows = (UPB month names-1)OVER year cols + 1; INT month gap = (page width - year cols*month width + 1)OVER year cols; INT year width = year cols*(month width+month gap)-month gap; INT year lines = year rows*month lines;
MODE MONTHBOX = [month lines, month width]CHAR; MODE YEARBOX = [year lines, year width]CHAR;
INT week start = 1; # Sunday #
PROC days in month = (INT year, month)INT: CASE month IN 31, IF year MOD 4 EQ 0 AND year MOD 100 NE 0 OR year MOD 400 EQ 0 THEN 29 ELSE 28 FI, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ESAC;
PROC day of week = (INT year, month, day)INT: ( # Day of the week by Zeller’s Congruence algorithm from 1887 # INT y := year, m := month, d := day, c; IF m <= 2 THEN m +:= 12; y -:= 1 FI; c := y OVER 100; y %*:= 100; (d - 1 + ((m + 1) * 26) OVER 10 + y + y OVER 4 + c OVER 4 - 2 * c) MOD 7 );
MODE SIMPLEOUT = UNION(STRING, []STRING, INT);
PROC cputf = (REF[]CHAR out, FORMAT fmt, SIMPLEOUT argv)VOID:( FILE f; STRING s; associate(f,s); putf(f, (fmt, argv)); out[:UPB s]:=s; close(f) );
PROC month repr = (INT year, month)MONTHBOX:( MONTHBOX month box; FOR line TO UPB month box DO month box[line,]:=" "* 2 UPB month box OD; STRING month name = month names[month];
# center the title # cputf(month box[1,(month width - UPB month name ) OVER 2+1:], $g$, month name); cputf(month box[2,], weekday fmt, weekday names);
INT first day := day of week(year, month, 1); FOR day TO days in month(year, month) DO INT line = (day+first day-week start) OVER UPB weekday names + month heading lines + 1; INT char =((day+first day-week start) MOD UPB weekday names)*(day width+day gap) + 1; cputf(month box[line,char:char+day width-1],$g(-day width)$, day) OD; month box );
PROC year repr = (INT year)YEARBOX:( YEARBOX year box; FOR line TO UPB year box DO year box[line,]:=" "* 2 UPB year box OD; FOR month row FROM 0 TO year rows-1 DO FOR month col FROM 0 TO year cols-1 DO INT month = month row * year cols + month col + 1; IF month > UPB month names THEN done ELSE INT month col width = month width+month gap; year box[ month row*month lines+1 : (month row+1)*month lines, month col*month col width+1 : (month col+1)*month col width-month gap ] := month repr(year, month) FI OD OD; done: year box );
INT center = (year cols*(month width+month gap) - month gap - 1) OVER 2; INT indent = (page width - year width) OVER 2;
printf(( $n(indent + center - 9)k g l$, "[Insert Snoopy here]", $n(indent + center - 1)k 4d l$, year, $l$, $n(indent)k n(year width)(g) l$, year repr(year) ))
);
main: ( CO inspired by http://www.ee.ryerson.ca/~elf/hack/realmen.html
Real Programmers Don't Use PASCAL - Ed Post Datamation, volume 29 number 7, July 1983 THE REAL PROGRAMMER'S NATURAL HABITAT
"Taped to the wall is a line-printer Snoopy calender for the year 1969." CO
INT mankind stepped on the moon = 1969, line printer width = 80; # as at 1969! # print calendar(mankind stepped on the moon, line printer width)
)</lang> Output:
[Insert Snoopy here] 1969 January February March Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa 1 2 3 4 1 1 5 6 7 8 9 10 11 2 3 4 5 6 7 8 2 3 4 5 6 7 8 12 13 14 15 16 17 18 9 10 11 12 13 14 15 9 10 11 12 13 14 15 19 20 21 22 23 24 25 16 17 18 19 20 21 22 16 17 18 19 20 21 22 26 27 28 29 30 31 23 24 25 26 27 28 23 24 25 26 27 28 29 30 31 April May June Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa 1 2 3 4 5 1 2 3 1 2 3 4 5 6 7 6 7 8 9 10 11 12 4 5 6 7 8 9 10 8 9 10 11 12 13 14 13 14 15 16 17 18 19 11 12 13 14 15 16 17 15 16 17 18 19 20 21 20 21 22 23 24 25 26 18 19 20 21 22 23 24 22 23 24 25 26 27 28 27 28 29 30 25 26 27 28 29 30 31 29 30 July August September Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa 1 2 3 4 5 1 2 1 2 3 4 5 6 6 7 8 9 10 11 12 3 4 5 6 7 8 9 7 8 9 10 11 12 13 13 14 15 16 17 18 19 10 11 12 13 14 15 16 14 15 16 17 18 19 20 20 21 22 23 24 25 26 17 18 19 20 21 22 23 21 22 23 24 25 26 27 27 28 29 30 31 24 25 26 27 28 29 30 28 29 30 31 October November December Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa 1 2 3 4 1 1 2 3 4 5 6 5 6 7 8 9 10 11 2 3 4 5 6 7 8 7 8 9 10 11 12 13 12 13 14 15 16 17 18 9 10 11 12 13 14 15 14 15 16 17 18 19 20 19 20 21 22 23 24 25 16 17 18 19 20 21 22 21 22 23 24 25 26 27 26 27 28 29 30 31 23 24 25 26 27 28 29 28 29 30 31 30
J
Solution: <lang j>require 'dates format' NB. J6.x require 'dates general/misc/format' NB. J7.x calBody=: (1 1 }. _1 _1 }. ":)@(-@(<.@%&22)@[ ]\ calendar@]) calTitle=: (<: - 22&|)@[ center '[Insert Snoopy here]' , ,:~ ":@] formatCalendar=: calTitle , calBody</lang> Example use: <lang j> 80 formatCalendar 1969
[Insert Snoopy here] 1969 Jan │ Feb │ Mar Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa 1 2 3 4│ 1│ 1 5 6 7 8 9 10 11│ 2 3 4 5 6 7 8│ 2 3 4 5 6 7 8 12 13 14 15 16 17 18│ 9 10 11 12 13 14 15│ 9 10 11 12 13 14 15 19 20 21 22 23 24 25│ 16 17 18 19 20 21 22│ 16 17 18 19 20 21 22 26 27 28 29 30 31 │ 23 24 25 26 27 28 │ 23 24 25 26 27 28 29 │ │ 30 31
─────────────────────┼─────────────────────┼─────────────────────
Apr │ May │ Jun Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa 1 2 3 4 5│ 1 2 3│ 1 2 3 4 5 6 7 6 7 8 9 10 11 12│ 4 5 6 7 8 9 10│ 8 9 10 11 12 13 14 13 14 15 16 17 18 19│ 11 12 13 14 15 16 17│ 15 16 17 18 19 20 21 20 21 22 23 24 25 26│ 18 19 20 21 22 23 24│ 22 23 24 25 26 27 28 27 28 29 30 │ 25 26 27 28 29 30 31│ 29 30 │ │
─────────────────────┼─────────────────────┼─────────────────────
Jul │ Aug │ Sep Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa 1 2 3 4 5│ 1 2│ 1 2 3 4 5 6 6 7 8 9 10 11 12│ 3 4 5 6 7 8 9│ 7 8 9 10 11 12 13 13 14 15 16 17 18 19│ 10 11 12 13 14 15 16│ 14 15 16 17 18 19 20 20 21 22 23 24 25 26│ 17 18 19 20 21 22 23│ 21 22 23 24 25 26 27 27 28 29 30 31 │ 24 25 26 27 28 29 30│ 28 29 30 │ 31 │
─────────────────────┼─────────────────────┼─────────────────────
Oct │ Nov │ Dec Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa 1 2 3 4│ 1│ 1 2 3 4 5 6 5 6 7 8 9 10 11│ 2 3 4 5 6 7 8│ 7 8 9 10 11 12 13 12 13 14 15 16 17 18│ 9 10 11 12 13 14 15│ 14 15 16 17 18 19 20 19 20 21 22 23 24 25│ 16 17 18 19 20 21 22│ 21 22 23 24 25 26 27 26 27 28 29 30 31 │ 23 24 25 26 27 28 29│ 28 29 30 31 │ 30 │ </lang>
PicoLisp
This "calendar" is nicely formated, and fits into 20 columns ;-) <lang PicoLisp>(de cal (Year)
(prinl "====== " Year " ======") (for Dat (range (date Year 1 1) (date Year 12 31)) (let D (date Dat) (tab (3 3 4 8) (when (= 1 (caddr D)) (get *Mon (cadr D)) ) (caddr D) (day Dat *Day) (when (=0 (% (inc Dat) 7)) (pack "Week " (week Dat)) ) ) ) ) )
(cal 1969)</lang> Output:
====== 1969 ====== Jan 1 Wed 2 Thu 3 Fri 4 Sat 5 Sun 6 Mon Week 2 7 Tue .... 28 Sat 29 Sun 30 Mon Week 27 Jul 1 Tue 2 Wed 3 Thu 4 Fri .... 25 Thu 26 Fri 27 Sat 28 Sun 29 Mon Week 53 30 Tue 31 Wed
Python
The Python calendar.pryear function prints calendars with the following formatting options: optional parameters w, l, and c are for date column width, lines per week, and number of spaces between month columns, respectively.
Although rumoured to be getting an anti-gravity module, Python as yet does not include a snoopy module ;-) <lang python>>>> import calendar >>> help(calendar.prcal) Help on method pryear in module calendar:
pryear(self, theyear, w=0, l=0, c=6, m=3) method of calendar.TextCalendar instance
Print a years calendar.
>>> prcal(1969, m=4)
1969
January February March April
Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
1 2 3 4 5 1 2 1 2 1 2 3 4 5 6 6 7 8 9 10 11 12 3 4 5 6 7 8 9 3 4 5 6 7 8 9 7 8 9 10 11 12 13
13 14 15 16 17 18 19 10 11 12 13 14 15 16 10 11 12 13 14 15 16 14 15 16 17 18 19 20 20 21 22 23 24 25 26 17 18 19 20 21 22 23 17 18 19 20 21 22 23 21 22 23 24 25 26 27 27 28 29 30 31 24 25 26 27 28 24 25 26 27 28 29 30 28 29 30
31
May June July August
Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
1 2 3 4 1 1 2 3 4 5 6 1 2 3 5 6 7 8 9 10 11 2 3 4 5 6 7 8 7 8 9 10 11 12 13 4 5 6 7 8 9 10
12 13 14 15 16 17 18 9 10 11 12 13 14 15 14 15 16 17 18 19 20 11 12 13 14 15 16 17 19 20 21 22 23 24 25 16 17 18 19 20 21 22 21 22 23 24 25 26 27 18 19 20 21 22 23 24 26 27 28 29 30 31 23 24 25 26 27 28 29 28 29 30 31 25 26 27 28 29 30 31
30
September October November December
Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
1 2 3 4 5 6 7 1 2 3 4 5 1 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 6 7 8 9 10 11 12 3 4 5 6 7 8 9 8 9 10 11 12 13 14
15 16 17 18 19 20 21 13 14 15 16 17 18 19 10 11 12 13 14 15 16 15 16 17 18 19 20 21 22 23 24 25 26 27 28 20 21 22 23 24 25 26 17 18 19 20 21 22 23 22 23 24 25 26 27 28 29 30 27 28 29 30 31 24 25 26 27 28 29 30 29 30 31
>>> </lang>
Ruby
<lang ruby>require 'date'
def cal(year)
months = (1..12).collect do |month| rows = [Date::MONTHNAMES[month].center(20), "Su Mo Tu We Th Fr Sa"]
days = [] date = Date.new(year, month, 1, Date::ENGLAND) date.wday.times { days.push " " } while date.month == month days.push("%2d" % date.mday) date += 1 end (42 - days.length).times { days.push " " }
days.each_slice(7) { |week| rows.push(week.join " ") } next rows end
rows = ["[Snoopy]".center(130), "#{year}".center(130)] months.each_slice(6) do |half| rows.push " " half[0].each_index do |i| rows.push(half.map {|a| a[i]}.join " ") end end return rows.join("\n")
end
case ARGV.length when 1
puts cal(Integer(ARGV[0]))
else
raise "usage: #{$0} year"
end</lang>
Tcl
Due to the prevalence of 80 column devices instead of 132 column ones, this code produces 3 months at a time instead of 4. <lang tcl>package require Tcl 8.5
- Produce information about the days in a month, without any assumptions about
- what those days actually are.
proc calMonthDays {timezone locale year month} {
set days {} set moment [clock scan [format "%04d-%02d-00 12:00" $year $month] \
-timezone $timezone -locale $locale -format "%Y-%m-%d %H:%M"]
while 1 {
set moment [clock add $moment 1 day] lassign [clock format $moment -timezone $timezone -locale $locale \ -format "%m %d %u"] m d dow if {[scan $m %d] != $month} { return $days } lappend days $moment [scan $d %d] $dow
}
}
proc calMonth {year month timezone locale} {
set dow 0 set line "" set lines {} foreach {t day dayofweek} [calMonthDays $timezone $locale $year $month] {
if {![llength $lines]} {lappend lines $t} if {$dow > $dayofweek} { lappend lines [string trimright $line] set line "" set dow 0 } while {$dow < $dayofweek-1} { append line " " incr dow } append line [format "%2d " $day] set dow $dayofweek
} lappend lines [string trimright $line]
}
proc cal3Month {year month timezone locale} {
# Extract the month data set d1 [lassign [calMonth $year $month $timezone $locale] t1]; incr month set d2 [lassign [calMonth $year $month $timezone $locale] t2]; incr month set d3 [lassign [calMonth $year $month $timezone $locale] t3] # Print the header line of month names foreach t [list $t1 $t2 $t3] {
set m [clock format $t -timezone $timezone -locale $locale -format "%B"] set l [expr {10 + [string length $m]/2}] puts -nonewline [format "%-25s" [format "%*s" $l $m]]
} puts "" # Print the month days foreach l1 $d1 l2 $d2 l3 $d3 {
puts [format "%-25s%-25s%s" $l1 $l2 $l3]
}
}
proc cal {{year ""} {timezone :localtime} {locale en}} {
if {$year eq ""} {
set year [clock format [clock seconds] -format %Y]
} puts [format "%40s" "-- $year --"] foreach m {1 4 7 10} {
puts "" cal3Month $year $m $timezone $locale
}
}
proc snoopy {} {
puts [format "%43s\n" {[Snoopy Picture]}]
}
snoopy cal</lang> Which produces this output:
[Snoopy Picture] -- 2011 -- January February March 1 2 1 2 3 4 5 6 1 2 3 4 5 6 3 4 5 6 7 8 9 7 8 9 10 11 12 13 7 8 9 10 11 12 13 10 11 12 13 14 15 16 14 15 16 17 18 19 20 14 15 16 17 18 19 20 17 18 19 20 21 22 23 21 22 23 24 25 26 27 21 22 23 24 25 26 27 24 25 26 27 28 29 30 28 28 29 30 31 31 April May June 1 2 3 1 1 2 3 4 5 4 5 6 7 8 9 10 2 3 4 5 6 7 8 6 7 8 9 10 11 12 11 12 13 14 15 16 17 9 10 11 12 13 14 15 13 14 15 16 17 18 19 18 19 20 21 22 23 24 16 17 18 19 20 21 22 20 21 22 23 24 25 26 25 26 27 28 29 30 23 24 25 26 27 28 29 27 28 29 30 30 31 July August September 1 2 3 1 2 3 4 5 6 7 1 2 3 4 4 5 6 7 8 9 10 8 9 10 11 12 13 14 5 6 7 8 9 10 11 11 12 13 14 15 16 17 15 16 17 18 19 20 21 12 13 14 15 16 17 18 18 19 20 21 22 23 24 22 23 24 25 26 27 28 19 20 21 22 23 24 25 25 26 27 28 29 30 31 29 30 31 26 27 28 29 30 October November December 1 2 1 2 3 4 5 6 1 2 3 4 3 4 5 6 7 8 9 7 8 9 10 11 12 13 5 6 7 8 9 10 11 10 11 12 13 14 15 16 14 15 16 17 18 19 20 12 13 14 15 16 17 18 17 18 19 20 21 22 23 21 22 23 24 25 26 27 19 20 21 22 23 24 25 24 25 26 27 28 29 30 28 29 30 26 27 28 29 30 31 31
If a different year is chosen, it's printed… <lang tcl>snoopy cal 1969</lang>
[Snoopy Picture] -- 1969 -- January February March 1 2 3 4 5 1 2 1 2 6 7 8 9 10 11 12 3 4 5 6 7 8 9 3 4 5 6 7 8 9 13 14 15 16 17 18 19 10 11 12 13 14 15 16 10 11 12 13 14 15 16 20 21 22 23 24 25 26 17 18 19 20 21 22 23 17 18 19 20 21 22 23 27 28 29 30 31 24 25 26 27 28 24 25 26 27 28 29 30 31 April May June 1 2 3 4 5 6 1 2 3 4 1 7 8 9 10 11 12 13 5 6 7 8 9 10 11 2 3 4 5 6 7 8 14 15 16 17 18 19 20 12 13 14 15 16 17 18 9 10 11 12 13 14 15 21 22 23 24 25 26 27 19 20 21 22 23 24 25 16 17 18 19 20 21 22 28 29 30 26 27 28 29 30 31 23 24 25 26 27 28 29 30 July August September 1 2 3 4 5 6 1 2 3 1 2 3 4 5 6 7 7 8 9 10 11 12 13 4 5 6 7 8 9 10 8 9 10 11 12 13 14 14 15 16 17 18 19 20 11 12 13 14 15 16 17 15 16 17 18 19 20 21 21 22 23 24 25 26 27 18 19 20 21 22 23 24 22 23 24 25 26 27 28 28 29 30 31 25 26 27 28 29 30 31 29 30 October November December 1 2 3 4 5 1 2 1 2 3 4 5 6 7 6 7 8 9 10 11 12 3 4 5 6 7 8 9 8 9 10 11 12 13 14 13 14 15 16 17 18 19 10 11 12 13 14 15 16 15 16 17 18 19 20 21 20 21 22 23 24 25 26 17 18 19 20 21 22 23 22 23 24 25 26 27 28 27 28 29 30 31 24 25 26 27 28 29 30 29 30 31
The code also handles Julian/Gregorian switch dates correctly, but must be told what locale to format the switch as and for what timezone in that case. For example, Spain was one of the first countries to make the change: <lang tcl>snoopy cal 1582 :Europe/Madrid es_ES</lang>
[Snoopy Picture] -- 1582 -- enero febrero marzo 1 2 3 4 5 6 7 1 2 3 4 1 2 3 4 8 9 10 11 12 13 14 5 6 7 8 9 10 11 5 6 7 8 9 10 11 15 16 17 18 19 20 21 12 13 14 15 16 17 18 12 13 14 15 16 17 18 22 23 24 25 26 27 28 19 20 21 22 23 24 25 19 20 21 22 23 24 25 29 30 31 26 27 28 26 27 28 29 30 31 abril mayo junio 1 1 2 3 4 5 6 1 2 3 2 3 4 5 6 7 8 7 8 9 10 11 12 13 4 5 6 7 8 9 10 9 10 11 12 13 14 15 14 15 16 17 18 19 20 11 12 13 14 15 16 17 16 17 18 19 20 21 22 21 22 23 24 25 26 27 18 19 20 21 22 23 24 23 24 25 26 27 28 29 28 29 30 31 25 26 27 28 29 30 30 julio agosto septiembre 1 1 2 3 4 5 1 2 2 3 4 5 6 7 8 6 7 8 9 10 11 12 3 4 5 6 7 8 9 9 10 11 12 13 14 15 13 14 15 16 17 18 19 10 11 12 13 14 15 16 16 17 18 19 20 21 22 20 21 22 23 24 25 26 17 18 19 20 21 22 23 23 24 25 26 27 28 29 27 28 29 30 31 24 25 26 27 28 29 30 30 31 octubre noviembre diciembre 1 2 3 4 15 16 17 1 2 3 4 5 6 7 1 2 3 4 5 18 19 20 21 22 23 24 8 9 10 11 12 13 14 6 7 8 9 10 11 12 25 26 27 28 29 30 31 15 16 17 18 19 20 21 13 14 15 16 17 18 19 22 23 24 25 26 27 28 20 21 22 23 24 25 26 29 30 27 28 29 30 31
As can be seen, a Real Programmer has many intricacies to deal with!