#!/usr/local/bin/perl -w use strict; use POSIX; sub isleap($) { my ($Y) = @_; return (($Y % 4) == 0 && ($Y % 100) != 0) || ($Y % 400) == 0; } my @dom = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31); sub day_of_month($$) { my ($Y, $m) = @_; my $days = $dom[$m - 1] + ($m == 2 && isleap($Y)); return $days; } my $YMD_OFFSET = -60; my $YMD_ORIG_YEAR = 1600; my @sod = (0, 31, 61, 92,122,153,184,214,245,275,306,337); my $DAY_MINUS_MJD = 94553; my $MJD_AJD = 2400000.5; sub divl($$) { my ($x, $y) = @_; return floor($x / $y); } sub modl($$) { my ($x, $y) = @_; return $x - floor($x / $y) * $y; } sub ymd_to_mjd($$$) { my ($Y, $m, $d) = @_; my $yy = $Y + divl($m, 12) - $YMD_ORIG_YEAR; my $mm = modl($m, 12) - 3; if ($mm < 0) { $yy--; $mm += 12; } my $dd = $d - 1; my $uu = divl($yy, 4) - divl($yy, 100) + divl($yy, 400); my $mjd = $yy * 365 + $sod[$mm] + $dd + $uu - $YMD_OFFSET - $DAY_MINUS_MJD; return $mjd; } my $D1 = 365; my $D4 = 1461; my $D100 = 36524; my $D400 = 146097; sub mjd_to_ymd($) { my ($mjd) = @_; $mjd += $YMD_OFFSET + $DAY_MINUS_MJD; my $y400 = divl($mjd, $D400); my $r400 = modl($mjd, $D400); my $y100 = divl($r400, $D100); my $r100 = modl($r400, $D100); my $y4 = divl($r100, $D4); my $r4 = modl($r100, $D4); my $y1 = divl($r4, $D1); my $r1 = modl($r4, $D1); my $yy = (($y400 * 4 + $y100) * 25 + $y4) * 4 + $y1; my $mm = 1; while ($mm < 12 && $sod[$mm] <= $r1) { $mm++; } $mm--; my $dd = $r1 - $sod[$mm]; if ($y100 == 4 || $y1 == 4) { $yy--; $mm = 11; $dd = 28; } my $Y = $yy + $YMD_ORIG_YEAR; my $m = $mm + 3; if ($m > 12) { $Y++; $m -= 12; } my $d = $dd + 1; return ($Y, $m, $d); } sub week_of_mjd($) { my ($mjd) = @_; $mjd += $DAY_MINUS_MJD; my $r = modl($mjd - 1, 7); return $r; } sub mjd_to_ajd($) { my ($mjd) = @_; return $mjd + $MJD_AJD; } sub ajd_to_mjd($) { my ($ajd) = @_; return $ajd - $MJD_AJD; } sub cal($$) { my @mm = ("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"); my ($Y, $m) = @_; my $w = week_of_mjd(ymd_to_mjd($Y, $m, 1)); my $s = $mm[$m - 1] . " $Y"; printf("%*s%s\n", (20 - length($s)) / 2, "", $s); printf("Su Mo Tu We Th Fr Sa\n"); my $i; for ($i = 0; $i < $w; $i++) { print $i + 1 == $w ? " " : " "; } my $l = 0; my $d; for ($d = 1; $d <= day_of_month($Y, $m); $d++) { if ($w != 0) { print " "; } printf("%2d", $d); $w++; if ($w == 7) { print "\n"; $w = 0; $l++; } } if ($w != 0) { print "\n"; $l++; } while ($l < 6) { print "\n"; $l++; } } sub ymd_test() { my ($Y, $m); for ($Y = 2000; $Y < 2400; $Y++) { for ($m = 1; $m <= 12; $m++) { cal($Y, $m); } } } ymd_test(); exit 0;