Path: utzoo!mnetor!uunet!seismo!sundc!pitstop!sun!decwrl!navion.dec.com!fulton From: fulton@navion.dec.com (10-Feb-1988 0958) Newsgroups: comp.sys.ibm.pc Subject: Re: perpetual calendar (also day of week) Message-ID: <8802101657.AA08427@decwrl.dec.com> Date: 10 Feb 88 17:58:00 GMT Organization: Digital Equipment Corporation Lines: 119 Robert_A_Freed@cup.portal.com writes: >In article <1217@mtuxo.UUCP> khreb@mtuxo.UUCP (01274-K.ROSEN) writes >to sci.math: > >>The day of the week of day k, of month m (where a year is >>considered to start in March, so that March is month 1 of that year and >>January is considered the 11th month of the previous year and >>February the twelfth month of that year), of year >>100C + Y, where C is the century and Y is the year of the >>century, is given by the remainder of >> >> k + [2.6m - 0.2] - 2C + Y + [Y/4] + [C/4] >> >>when divided by 7, where Sunday is represented by a remainder of 0, >>Monday by 1, etc. >> >>For instance, for January 1, 1900 we have C=18, Y=99, m=11, and k=1 >>(since January is considered the 11th month of 1899 for this >>calculation). The formula becomes 1+28-36+99+4+24 which leaves a >>remainder of 1 when divided by 7. Hence this day was a Monday. >> >>For a derivation of this formula see my book ELEMENTARY NUMBER THEORY >>AND ITS APPLICATIONS, Addison-Wesley, either first edition 1984 or >>the new second edition, 1988. The formula is messy because of the >>problem of different numbers of days in months and leap years occurring >>every 4 years, except for even century years not divisible by 400. >> >> Ken Rosen, AT&T >> 201-957-3691 > >(A similar, but slightly less elegant, formula was recently discussed in >comp.sys.ibm.pc as well.) > >I believe this is known as Zeller's congruence. It's also cited in the >text book, Elementary_Number_Theory, by Uspensky and Heaslet. I first >noticed this little gem in a 1965 book, Problems_for_Computer_Solution, >by Fred Gruenberger and George Jaffray. (The subject computer was the >IBM 1620. If that doesn't date me, I don't know what will! :-) > >Two small comments about the above formula: > >1. [2.6m - 0.2] can be calculated as [(13m - 1)/5] to avoid the > overhead (and possible inaccuracy) of floating-point arithmetic. > (Although not stated in the formulation, the square brackets [...] > imply integer truncation.) > >2. This applies only to the current (Gregorian) calendar, which was > established October 15, 1582, but was not adopted by Great Britain > (and the American colonies) until 1752. > >The formula is particularly efficient for computer solution since it >involves only short integer arithmetic and a single conditional test >(for January-February). And, unlike many other day-of-the-week >solutions I've seen, this one handles non-leap century years (such as >1900 and 2100) correctly. > >Bob Freed Internet: Robert_A_Freed@cup.portal.com >Newton Centre, MA UUCP: sun!portal!cup.portal.com!Robert_A_Freed I have been intrigued by the above formula, and I coded it up in Logitech Modula-2 to try it out. It appears that there are some cases where it doesn't work quite right. For instance: October 1, 1910 has: k = 1 m = 8 C = 19 Y = 10 Thus you achieve: k + [2.6m - 0.2] - 2C + Y + [Y/4] + [C/4] = 1 + [2.6 * 8 - 0.2] - 2 * 19 + 10 + [10 / 4] + [19 / 4] = 1 + [20.8 - 0.2] - 38 + 10 + [2.5] + [4.75] = 1 + [20.6] - 38 + 10 + 2 + 4 = 1 + 20 - 38 + 10 + 2 + 4 = -1 Then you have -1 MOD 7 => -1, which does not equate to any of the numbers assigned to Sunday thru Saturday, namely 0 thru 6. There are many cases in which the above formula generates a negative number, and it is not always -1. (I used a program I wrote that generates correct dates (it accounts correctly for leap year, as does the above formula) and ran the output of that program into the input of my program for the above formula; that's how I discovered this problem.) For all cases in which the above formula generates a negative number, applying the following fix before doing the MOD 7 works: WHILE DayOfWeek < 0 DO DayOfWeek := DayOfWeek + 7; END (* while *); (Note: I actually code DayOfWeek := DayOfWeek + 7; as INC( DayOfWeek, 7 ); I showed it the way I did for those of you not familiar with Modula-2.) I guess that this is an after-the-fact kludge; perhaps the original formula could be changed so that the result doesn't require "fixing" if it comes out negative. - Cathy Fulton uucp: ...decwrl!comet.dec.com!fulton ARPA: fulton@comet.dec.com