need to change iphlen earlier; icmp_error needs original ip_len; cleanups
[unix-history] / usr / src / usr.bin / cal / README
CommitLineData
b19a0abd
KB
1Program Design
2
3This program exactly duplicates the operation of the original unix "cal"
4program. It was designed with that intent, so no "improvements" were made
5to either the command line syntax or to the error reporting. The main
6goal was to allow replacement of the existing binary with a freely
7redistibutable version without breaking any existing applications that
8might be built on top of the original.
9
10The date routines were written from scratch, basically from first
11principles. The algorithm for calculating the day of week from any
12gregorian date was "reverse engineered". This was necessary as most of
13the documented algorithms have to do with date calculations for other
14calendars (e.g. julian) and are only accurate when converted to gregorian
15within a narrow range of dates.
16
17I take 1 jan 1 to be a Saturday because that's what cal says and I couldn't
18change that even if I was dumb enough to try. From this we can easily
19calculate the day of week for any date. The algorithm for a zero based
20day of week:
21
22 calculate the number of days in all prior years (year-1)*365
23 add the number of leap years (days?) since year 1
24 (not including this year as that is covered later)
25 add the day number within the year
26 this compensates for the non-inclusive leap year
27 calculation
28 if the day in question occurs before the gregorian reformation
29 (3 sep 1752 for our purposes), then simply return
30 (value so far - 1 + SATURDAY's value of 6) modulo 7.
31 if the day in question occurs during the reformation (3 sep 1752
32 to 13 sep 1752 inclusive) return THURSDAY. This is my
33 idea of what happened then. It does not matter much as
34 this program never tries to find day of week for any day
35 that is not the first of a month.
36 otherwise, after the reformation, use the same formula as the
37 days before with the additional step of subtracting the
38 number of days (11) that were adjusted out of the calendar
39 just before taking the modulo.
40
41It must be noted that the number of leap years calculation is sensitive
42to the date for which the leap year is being calculated. A year that occurs
43before the reformation is determined to be a leap year if its modulo of
444 equals zero. But after the reformation, a year is only a leap year if
45its modulo of 4 equals zero and its modulo of 100 does not. Of course,
46there is an exception for these century years. If the modulo of 400 equals
47zero, then the year is a leap year anyway. This is, in fact, what the
48gregorian reformation was all about (a bit of error in the old algorithm
49that caused the calendar to be inaccurate.)
50
51Once we have the day in year for the first of the month in question, the
52rest is trivial. Running diff on any output of this program and the
53equivalent output from the original cal reports no difference. This was
54confirmed by a script that ran them for all possible inputs (and took
55approximately 36 hours to complete on a sun-3.)