NetBSD/usr.bin/cal
wennmach 8d67a1ce88 Fix a documentation bug in this man page: The Gregorian Reformation in Great
Britain and its colonies eliminated 11 days (not 10), following
September 2, 1752.

From "A.D. 1751. Anno vicesimo quarto GEORGII II. CAP. XXIII.
      An Act for Regulating the Commencement of the Year; and for
      Correcting the Calendar now in Use.":

"... and that the natural Day next immediately following the said 2nd Day of
 *September* [1752], shall be called, reckoned and accounted to be the 14th
 Day of *September*, omitting for that Time only the 11 intermediate nominal
 Days of the common Calendar;

 and that the several natural Days, which shall follow and succeed next after
 the said 14th Day of *September*, shall be respectively called, reckoned and
 numbered forwards in numerical Order from the said 14th Day of *September*,
 according to the Order and Succession of Days now used in the present
 Calendar; "

Added a caution note on using cal for very old dates.

Problem mentionned in PR 5215 by John Franklin (franklin@bev.net).

Thanks to Perry Metzger for his comments and for reviewing this man page.
1999-11-03 14:32:25 +00:00
..
cal.1 Fix a documentation bug in this man page: The Gregorian Reformation in Great 1999-11-03 14:32:25 +00:00
cal.c
Makefile
README

The cal(1) date routines were written from scratch, basically from first
principles.  The algorithm for calculating the day of week from any
Gregorian date was "reverse engineered".  This was necessary as most of
the documented algorithms have to do with date calculations for other
calendars (e.g. julian) and are only accurate when converted to gregorian
within a narrow range of dates.

1 Jan 1 is a Saturday because that's what cal says and I couldn't change
that even if I was dumb enough to try.  From this we can easily calculate
the day of week for any date.  The algorithm for a zero based day of week:

	calculate the number of days in all prior years (year-1)*365
	add the number of leap years (days?) since year 1 
		(not including this year as that is covered later)
	add the day number within the year
		this compensates for the non-inclusive leap year
		calculation
	if the day in question occurs before the gregorian reformation
		(3 sep 1752 for our purposes), then simply return 
		(value so far - 1 + SATURDAY's value of 6) modulo 7.
	if the day in question occurs during the reformation (3 sep 1752
		to 13 sep 1752 inclusive) return THURSDAY. This is my
		idea of what happened then. It does not matter much as
		this program never tries to find day of week for any day
		that is not the first of a month.
	otherwise, after the reformation, use the same formula as the
		days before with the additional step of subtracting the
		number of days (11) that were adjusted out of the calendar
		just before taking the modulo.

It must be noted that the number of leap years calculation is sensitive
to the date for which the leap year is being calculated.  A year that occurs
before the reformation is determined to be a leap year if its modulo of
4 equals zero.  But after the reformation, a year is only a leap year if
its modulo of 4 equals zero and its modulo of 100 does not.  Of course,
there is an exception for these century years.  If the modulo of 400 equals
zero, then the year is a leap year anyway.  This is, in fact, what the
gregorian reformation was all about (a bit of error in the old algorithm
that caused the calendar to be inaccurate.)

Once we have the day in year for the first of the month in question, the
rest is trivial.