Fuer welche Daten ist die Formel nicht anwendbar?
Der gregorianische Kalender zeichnet sich doch dadurch aus, dass es alle vier Jahre ein Schaltjahr gibt. Volle Jahrhunderte sind nur dann ein Schaltjahr, wenn sie durch 400 teilbar sind. Weitere Regeln gibt es nicht; die immer wieder diskutierten zusaetzlichen Schalttage jenseits des Jahres
3000 waeren eine Korrektur, sie sind AFAIK nicht Bestandteil des gregorianischen Kalenders.Und genau den beschriebenen Sachverhalt gibt die Funktion wieder. Das ist eigentlich relativ leicht nachzuvollziehen. Ich habe nun etwas "reverse engineering" probiert. Sehen wir uns die Funktion nochmals an:
int dayofweek(int y, int m, int d) { static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4}; y -= m < 3; return (y + y/4 - y/100 + y/400 + t[m-1] + d) % 7; }
Die Formel berechnet im Prinzip eine fortlaufende Tagesnummer. Da wir nur am Modulo-7-Ergebnis dieser Nummer interessiert sind, koennen wir der Einfachheit halber auch schon einzelne Summanden modulo 7 rechnen.
Fall 1: Das Datum liegt im Jaenner oder Februar:
Wir berechnen zuerst die Tage aller bisher vergangenen Jahre (daher y -=
1) seit einem (imaginaeren) Jahr 0. Das waere unter Beruecksichtigung der Schaltjahre:d1 = 365*y + y/4 - y/100 + y/400 = = 364*y + y + y/4 - y/100 + y/400
364*y ist immer durch 7 teilbar, liefert also zum Ergebnis modulo 7 keinen Beitrag und wird daher weggelassen.d1' = y + y/4 - y/100 + y/400
Als naechstes kommen die Tage, die in den bisher verganganen Monaten des aktuellen Jahres liegen. Wenn das gesuchte Datum im Jaenner liegt, sind das natuerlich d2 = 0, im Februar waeren es d2 = 31 (naemlich der gesamte Jaenner). Dies koennen wir wieder modulo 7 rechnen und kommen auf den naechsten Summanden
d2'[1, 2] = {0, 3}
Dies sind genau die Werte, die im Array t[] stehen. Dann addieren wir noch den Tag (d) dazu und erhalten den Wochentag
w = (d1' + d2' + d) % 7
Fall 2: Das Datum liegt in den Monaten Maerz bis Dezember:
In diesem Fall muessen wir bei der Berechnung der Schalttage das laufende Jahr mit einbeziehen, da der Februar ja bereits vorbei ist. Wir dekrementieren y diesmal also nicht und rechnen
d1 = 365*y + y/4 - y/100 + y/400 - 365
Die Subtraktion von 365 Tagen ist erforderlich, da wir hier das vollstaendige aktuelle Jahr (und nicht nur den eventuellen Schalttag) mitgerechnet haben, was natuerlich um 365 Tage zuviel sind. Wie zuvor vereinfachen wir wieder:
d1' = y + y/4 - y/100 + y/400 - 1
Jetzt kommen wieder die Tage, die in den bisher verganganen Monaten des aktuellen Jahres liegen. Fuer ein Datum in den Monaten Maerz...Dezember waeren dies
d2[3...12] = {59, 90, 120, 151, 181, 212, 243, 273, 304, 334}
Bei d1' haben wir ein stoerendes "-1" stehen, dieses packen wir in das d2 hinein und erhalten fuer d1" nun dieselbe Formel wie im Fall 1.
d1" = y + y/4 - y/100 + y/400 d2'[3...12] = {58, 89, 119, 150, 180, 211, 242, 272, 303, 333}
Das d2' koennen wir nun aus den bekannten Gruenden wieder modulo 7 rechnen:
d2"[3...12] = {2, 5, 0, 3, 5, 1, 4, 6, 2, 4}
Auch dies sind genau die Werte, die im Array t[] stehen. Nach Addition des Tages (d) erhalten wir wieder den Wochentag:
w = (d1" + d2" + d) % 7
Ich wuesste nicht, fuer welche Daten des gregorianischen Kalenders dieses Verfahren falsche Ergebnisse liefern sollte.