P
Pascal Le Bail
Guest
Nicolas Mittelmaier wrote:
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.
--
Gruesse,
Pascal Le Bail, Wien
Meine Absenderadresse ist derzeit inaktiv. Siehe <http://swen.pascal.at/>.
Fuer welche Daten ist die Formel nicht anwendbar?Diese Formel ist jedoch nicht für wirklich alle (!) Daten anwendbar.
Insbesondere das 1. März 2000-Problem wird in dem von mir oben
geposteten Artikel beschrieben.
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.
--
Gruesse,
Pascal Le Bail, Wien
Meine Absenderadresse ist derzeit inaktiv. Siehe <http://swen.pascal.at/>.