|
|
1.1 ! root 1: Program Design ! 2: ! 3: This program exactly duplicates the operation of the original unix "cal" ! 4: program. It was designed with that intent, so no "improvements" were made ! 5: to either the command line syntax or to the error reporting. The main ! 6: goal was to allow replacement of the existing binary with a freely ! 7: redistibutable version without breaking any existing applications that ! 8: might be built on top of the original. ! 9: ! 10: The date routines were written from scratch, basically from first ! 11: principles. The algorithm for calculating the day of week from any ! 12: gregorian date was "reverse engineered". This was necessary as most of ! 13: the documented algorithms have to do with date calculations for other ! 14: calendars (e.g. julian) and are only accurate when converted to gregorian ! 15: within a narrow range of dates. ! 16: ! 17: I take 1 jan 1 to be a Saturday because that's what cal says and I couldn't ! 18: change that even if I was dumb enough to try. From this we can easily ! 19: calculate the day of week for any date. The algorithm for a zero based ! 20: day 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: ! 41: It must be noted that the number of leap years calculation is sensitive ! 42: to the date for which the leap year is being calculated. A year that occurs ! 43: before the reformation is determined to be a leap year if its modulo of ! 44: 4 equals zero. But after the reformation, a year is only a leap year if ! 45: its modulo of 4 equals zero and its modulo of 100 does not. Of course, ! 46: there is an exception for these century years. If the modulo of 400 equals ! 47: zero, then the year is a leap year anyway. This is, in fact, what the ! 48: gregorian reformation was all about (a bit of error in the old algorithm ! 49: that caused the calendar to be inaccurate.) ! 50: ! 51: Once we have the day in year for the first of the month in question, the ! 52: rest is trivial. Running diff on any output of this program and the ! 53: equivalent output from the original cal reports no difference. This was ! 54: confirmed by a script that ran them for all possible inputs (and took ! 55: approximately 36 hours to complete on a sun-3.)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.