#!/usr/local/bin/perl -w eval 'exec /usr/local/bin/perl -w -S $0 ${1+"$@"}' if 0; # not running under some shell package cal; use strict; $cal::num_args = scalar( @ARGV ); if( $cal::num_args == 0 ) { ( $cal::month, $cal::year ) = (localtime( time ))[ 4, 5 ]; $cal::month++; $cal::year += 1900; } elsif( $cal::num_args == 1 ) { if( $ARGV[ 0 ] !~ /^\d.*$/o ) { ( $cal::jd, $cal::yr ) = &get_flags( $ARGV[ 0 ] ); if( $cal::jd && !($cal::yr) ) { ( $cal::month, $cal::year ) = (localtime( time ))[ 4, 5 ]; $cal::month++; $cal::year += 1900; } if( $cal::yr ) { $cal::year = (localtime( time ))[ 5 ]; $cal::year += 1900; } } else { $cal::year = &get_year( $ARGV[ 0 ] ); } } elsif( $cal::num_args == 2 ) { if( $ARGV[ 0 ] !~ /^\d.*$/o ) { ( $cal::jd, $cal::yr ) = &get_flags( $ARGV[ 0 ] ); if( $cal::yr ) { print "INVALID FLAG. Can not use -y with year.\n"; &display_help(); } $cal::year = &get_year( $ARGV[ 1 ] ); } else { $cal::month = &get_month( $ARGV[ 0 ] ); $cal::year = &get_year( $ARGV[ 1 ] ); } } elsif( $cal::num_args == 3 ) { ( $cal::jd, $cal::yr ) = &get_flags( $ARGV[ 0 ] ); if( $cal::yr ) { print "INVALID FLAG. Can not use -y with month and year.\n"; &display_help(); } $cal::month = &get_month( $ARGV[ 1 ] ); $cal::year = &get_year( $ARGV[ 2 ] ); } else { print "TOO MANY ARGUMENTS.\n"; &display_help(); } if( $cal::year && $cal::month ) { &print_month( $cal::year, $cal::month ); } else { my( $i ); for( $i = 1; $i < 13; $i++ ) { &print_month( $cal::year, $i ); print "\n"; } } sub print_month { my( $year, $month ) = @_; my( @month ) = &make_month_array( $year, $month ); my( $title, $length, $diff, $left, $right ) = (); my( $day, $end, $x, $size ) = (); my( @months ) = ( '', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ); my( @days ) = ( ' Su', ' M', ' Tu', ' W', ' Th', ' F', ' Sa' ); $size = scalar( @month ); $title = "$months[ $month ] $year"; $length = length( $title ); $diff = 28 - $length; $right = int($diff / 2); $left = $diff - $right; $title = ' ' x $left."$title".' ' x $right; print "$title\n"; foreach $day (@days) { print "$day"; } $end = 0; for( $x = 0; $x < $size; $x++ ) { if( $end == 0 ) { print "\n"; } print "$month[ $x ]"; $end++; if( $end > 6 ) { $end = 0; } } print "\n"; } sub make_month_array { my( $year, $month ) = @_; my( @month_array, $numdays, $remain, $x, $y ) = (); my( $firstweekday ) = &day_of_week_num( $year, $month, 1 ); $numdays = &days_in_month( $year, $month ); $y = 1; if( $cal::jd ) { $y = &day_of_year( $year, $month, 1 ); } for( $x = 0; $x < $firstweekday; $x++ ) { $month_array[$x] = ' '; } if( !(($year == 1752) && ($month == 9)) ) { for( $x = 1; $x <= $numdays; $x++, $y++ ) { $month_array[$x + $firstweekday - 1] = sprintf( "%4d", $y); } } else { for( $x = 1; $x <= $numdays; $x++, $y++ ) { $month_array[$x + $firstweekday - 1] = sprintf( "%4d", $y); if( $y == 2 ) { $y = 13; } } } return( @month_array ); } sub day_of_week_num { my( $year, $month, $day ) = @_; my( $a, $y, $m, $d ) = (); $a = int( (14 - $month)/12 ); $y = $year - $a; $m = $month + (12 * $a) - 2; if( &is_julian( $year, $month ) ) { $d = (5 + $day + $y + int($y/4) + int(31*$m/12)) % 7; } else { $d = ($day + $y + int($y/4) - int($y/100) + int($y/400) + int(31*$m/12)) % 7; } return( $d ); } sub days_in_month { my( $year, $month ) = @_; my( @month_days ) = ( 0,31,28,31,30,31,30,31,31,30,31,30,31 ); if( ($month == 2) && (&is_leap_year( $year )) ) { $month_days[ 2 ] = 29; } elsif ( ($year == 1752) && ($month == 9) ) { $month_days[ 9 ] = 19; } return( $month_days[ $month ] ); } sub day_of_year { my( $year, $month, $day ) = @_; my( @days ) = ( 0,31,59,90,120,151,181,212,243,273,304,334,365 ); my ( $ly, $i ) = (); $ly = 0; if( (&is_leap_year( $year )) && ($month > 2) ) { $ly = 1; } if( $year == 1752 ) { for( $i = 9; $i < 13; $i++ ) { $days[ $i ] = $days[ $i ] - 11; } } return( $days[ $month - 1 ] + $day + $ly ) } sub is_leap_year { my( $year ) = @_; my( $bool ) = 0; if( &is_julian( $year, 1 ) ) { if( $year % 4 == 0 ) { $bool = 1; } } else { if( (($year % 4 == 0) && ($year % 100 != 0)) || ($year % 400 == 0) ) { $bool = 1; } } return( $bool ); } sub is_julian { my( $year, $month ) = @_; my( $bool ) = 0; if( ($year < 1752) || ($year == 1752 && $month <= 9) ) { $bool = 1; } return( $bool ); } sub get_month { my( $month ) = @_; if( $month < 1 || $month > 12 || $month !~ /^\d+$/o ) { print "INVALID MONTH ENTERED.\n"; &display_help(); } return( $month ); } sub get_year { my( $year ) = @_; if( $year < 1 || $year > 9999 || $year !~ /^\d+$/o ) { print "INVALID YEAR ENTERED.\n"; &display_help(); } return( $year ); } sub get_flags { my( $flags ) = @_; my( $jd, $yr ) = (); if( ($flags =~ /.[^jy\?]/o) || ($flags !~ /^-\w+/o) ) { print "INVALID FLAGS ENTERED.\n"; &display_help(); } if( $flags =~ /j/o ) { $jd = 1; } if( $flags =~ /y/o ) { $yr = 1; } if( $flags =~ /\?/o ) { &display_help(); } return( $jd, $yr ); } sub display_help { print < dates must be fully defined. Entering a year of 99 means 99 AD, not 1999 AD. =head1 DESCRIPTION cal.pl generates calendars from 1 AD through 9999 AD, in the following format. S< March 1999 Su M Tu W Th F 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 > It takes into account the conversion from the Julian Calendar to the Gregorian Calendar in September, 1752. Note that this was the date used in the UK and all of her colonies (including the U.S.). Thus, in September, 1752, there were only 19 days. Eleven days had to be removed from the calendar to make up for inaccuracies in the Julian Calendar. So, September 2, 1752 was followed by September 14, 1752 in the UK and all colonies, as shown below. S< September 1752 Su M Tu W Th F Sa 1 2 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 > The Julian calendar has a leap year every 4 years. The Gregorian calendar has a leap year based on the following: If the year is evenly divisible by 400, it is a leap year, else, if the year is evenly divisible by 4, and not evenly divisible by 100, it is a leap year. All other years are not leap years. There is some contention over whether 4 AD was a leap year or not. Not all the experts agree, as there was a counting error in the beginning of the Julian calendar with regards to leap years that had to be corrected, and thus some years that would normally have been leap years were not. This calendar assumes that 4 AD was indeed a leap year. =head1 FURTHER READING The calculations used in this calendar, as well as information on when the calendar was switched over, and the implications thereof, were obtained from information found at the following URL. If you would like to find out more about calendars, I highly suggest taking a look. F =head1 AUTHOR Michael E. Schechter mschechter@earthlink.net =head1 COPYRIGHT INFORMATION This application is distributed as part of the Perl Power Tools. Feel free to copy, modify, delete, or whatever you would like with this file, under the information contained in the GNU GPL. =cut