Why does "cal 9 1752" produce incorrect results?

Harald Fuchs fuchs at it.uka.de
Wed Nov 28 10:31:32 AEST 1990


Nathan.Torkington at comp.vuw.ac.nz (Nathan Torkington) writes:

>In article <3313 at ns-mx.uiowa.edu> khenry at umaxc.weeg.uiowa.edu (Ken Henry) writes:
>>Does anybody know why "cal 9 1752" produce incorrect
>>results?  It seems to be in the Unix systems I
>>checked (BSD 4.3, AIX 3.1).  

>I believe there was a date change sometime, where the civilised world lost
>a fortnight to allow the 'old calendar' to become the 'new calendar' which
>would be in sync with the seasons ...

You seem to think of the Julian -> Gregorian calendar shift, but that
was 1582 AD.
How about a little perl script? Doesn't handle Julian dates either
but should work for the Gregorian calendar. I'm sure one of the Perl
lords on the net will come up with a one-liner, but for the time being...

----------------- snip snip snippety snip ------------------------------
#!/usr/local/bin/perl
$0 =~ s:.*/::;
$[ = 1;
# Argument check
if ($#ARGV == 1) {
  $all = 1;
  $m = 1;
  $y = shift;
} elsif ($#ARGV == 2) {
  $m = shift;
  die "$0: bad month \"$m\"\n" if $m !~ /^\d{1,2}$/ || $m < 1 || $m > 12;
  $y = shift;
} else {
  die "Usage: $0 [month] year\n";
}
die "$0: bad year \"$y\"\n" if $y !~ /^\d{4}$/ || $y <= 1582;
# First weekday
$w = &wday (1, $m, $y) + 1;
print "$y\n";
if ($all) {
  for $m (1..12) { $w = &month ($m, $y, $w); }
} else {
  $w = &month ($m, $y, $w);
}

sub wday { # (d, m, y)
  # Day of the week, Gregorian calendar
  local ($d, $m, $y) = @_;
  local ($f) = $y * 365 + $d + 31 * ($m - 1);
  if ($m <= 2) {
    $y--;
  } else {
    $f -= int ($m * 0.4 + 2.3);
  }
  $f += int ($y / 4) - int (0.75 * int ($y / 100) + 0.75);
  # Return 0 for Monday, ..., 6 for Sunday
  ($f + 5) % 7;
}

sub month { # (m, y, w)
  # Print out one month
  local ($m, $y, $w) = @_;
  local (@l) = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
  $l[2]++ if !($y % 4) && $y % 100 || !($y % 400);
  local (@n) = (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec);
  print "\n$n[$m]\n\n";
  local (@wd) = (Mon, Tue, Wed, Thu, Fri, Sat, Sun);
  local ($_);
  for (1..$l[$m]) {
    printf "%s\t%2d\n", $wd[$w], $_;
    $w = ($w % 7) + 1;
  }
  $w;
}

# local variables:
# mode: perl
# end:
----------------- snip snip snippety snip ------------------------------
--

Harald Fuchs <fuchs at it.uka.de> <fuchs%it.uka.de at relay.cs.net> ...
<fuchs at telematik.informatik.uni-karlsruhe.dbp.de>   *gulp*



More information about the Comp.unix.questions mailing list