#!/usr/local/bin/pike #pragma strict_types typedef int(1..12) Month; typedef int(1..31) Day; typedef int(1..) Year; constant weekdays = ({ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }); string month_name( Month month ) { return ({ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" })[month-1]; } int(28..31) month_length( Month month, Year year ) { switch (month) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: return 31; case 4: case 6: case 9: case 11: return 30; case 2: if( (year % 4) || (!(year % 100) && ((year/100) % 4)) ) return 28; else return 29; } } int(0..6) weekday( Day day, Month month, Year year ) { int days = 365 * ( year - 1 ) + ( year - 1 ) / 4 - ( year - 1 ) / 100 + ( year - 1 ) / 400; // from full years for ( Month m = 1; m < month; m++ ) // complete months of current year days += month_length( m, year ); days += day; return [int(0..6)](days % 7); } array(array(Day)) cal_month( Month month, Year year ) { int(0..6) k = weekday( 1, month, year ); array(array(Day)) cal_table; array(Day) cal_row = [array(Day)]( ({ 0 }) * k + enumerate( month_length( month, year ), 1, 1 ) ); cal_table = cal_row / 7.0; if ( sizeof( cal_table[-1] ) != 7 ) cal_table[-1] += ( ({ 0 }) * ( 7 - (sizeof( cal_row ) % 7 ) ) ); return cal_table; } string cal_txt( Month month, Year year ) { string res = sprintf ( "%|21s\n", month_name( month ) + " " + (string)year ) + sprintf("%{%-!2s %}\n", weekdays); foreach ((array(array(string)))cal_month( month, year), array(string) row) { row = [array(string)]map( row, lambda( string s ){ return (s=="0") ? "" : s; } ); res += sprintf("%{%2s %}\n", row); } return res; } int main( int ac, array(string) av ) { Month month; Year year; switch(ac-1) { case 0: mapping m = localtime( time() ); month = [int(1..12)](m->mon + 1); year = [int(1..)](m->year + 1900); break; case 1: array(string) a; for ( int k = 1; k <= 12 ; k++ ) { a = av[0..0] + ({ (string)k }) + av[1..1]; int r = main( 3, a ); if ( r ) return r; } return 0; case 2: month = [int(1..12)](int)(av[1]); year = [int(1..)](int)(av[2]); break; default: werror( "%s: wrong number of arguments (should be 1 or 2: [month] year)\n", basename(av[0])); return 1; } if ( ( month < 1 ) || ( month > 12 ) || ( year < 1 ) ) { werror( "%s: unsupported arguments: month = %d, year = %d\n", basename(av[0]), month, year ); return 1; } write( cal_txt( month, year ) ); return 0; }