[Richard Suchenwirth] 2007-04-26 - A little fun project while waiting for a lengthy build: the following code produces a string with the calendar of one month (as a subset of what the Unix command of same name does), e.g. % cal April 2007 April 2007 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 Here's the code, densely textured :^) ---- proc cal {{month {}} {year {}}} { if {$year == {} && [regexp {^[0-9]+$} $month]} { return [cal {Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec} $month] } if {$month eq ""} {set month [clock format [clock sec] -format %B]} if {[llength $month] > 1} { set res {} foreach m $month { append res [cal $m $year]\n\n } return [string trimright $res] } if {$year eq ""} {set year [clock format [clock sec] -format %Y]} set res " $month $year\n Su Mo Tu We Th Fr Sa\n" set weekday [clock format [clock scan "1 $month $year"] -format %w] append res [string repeat " " $weekday] scan [clock format [clock scan "1 $month $year"] -format %m] %d decm set maxd [numberofdays $decm $year] for {set d 1} {$d <= $maxd} {incr d} { append res [format %3d $d] if {[incr weekday]>6} {append res \n; set weekday 0} } set res } proc numberofdays {month year} { if {$month==12} {set month 1; incr year} clock format [clock scan "[incr month]/1/$year 1 day ago"] \ -format %d } # Test: catch {console show} catch {wm withdraw .} puts [ cal Jan 2007 ] puts "\n" puts "List of month:\n [ cal {Apr May} ]\n" puts "Current month:\n [ cal "" 2007 ]" puts "Default is the current month:\n [ cal ]" ---- Someone else might want to take a look at the above code and add the appropriate localisation/internationalizations (so that the day and month names are displayed in the local language preferences, etc. ---- [wdb] simply great! ---- [MJ] - Added that if the month is a list of month names, the result will be a calender for all the months. % cal {Apr May} Apr 2007 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 May 2007 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 ---- [HJG] Added a little test. ---- [LV] Added the output of the default call. HOWEVER, one behavior missing from the above routine is the behavior if one supplies only a year: unable to convert date-time string "1 2007 2007" while executing "FreeScan $string $base $timezone $locale" (procedure "::tcl::clock::scan" line 70) invoked from within "clock scan "1 $month $year"" (procedure "cal" line 12) invoked from within "cal 2007 " invoked from within "puts "Year calendar output:\n [ cal 2007 ]"" (file "/tmp/cal.tcl" line 37) ---- [RS] Wrong call. The signature specifies that you can give an optional month, and if you have, an optional year. Call it right, get it right; call it wrong, get some error. One could add checks to change that (8.5?) error to a clearer one; but for Wiki examples I prefer to code as simple as possible :^) [MJ] Added functionality to display the whole year if the first argument is a number and the second empty anyway. (This arguably is a hack because it uses the month parameter as a year instead) [MJ] seem to gloss over the issue that the error message was unclear instead of any missing functionality. Only way to really resolve that is to do catches on the [clock scan ...] ---- [Category Date and Time]