Kalenderberechnungen
Motivation
Während meiner Tätigkeit als Softwareentwickler kam ich immer wieder mit der Berechnung von Kalenderdaten in Berührung. Die dabei benutzten Algorithmen und deren Erweiterungen möchte ich hier darstellen.
Dabei entsteht eine Abhandlung über Kalenderalgorithmen, der Versuch ihrer Erklärung und das Protokoll einer Umsetzung in die verschiedensten Programmiersprachen.
Vorbemerkungen
Alle Beispiele sind in keiner bestimmten Programmiersprache formuliert. Mir kommt es zunächst nur darauf an, die Algorithmen zu zeigen. Die Umsetzung in konkrete Programmiersprachen erläutere ich später. In diesem zweiten Teil der Abhandlung gehe ich von einem System aus, in dem es auf irgendeine Weise möglich ist, einer Funktion mehrere Paramenter mitzugeben, wie auch der aufrufenden Funktion mehrere Werte zurückzugeben.
Allgemeine Einführung
Hier möchte ich Herrn Prof. Dr. Rudolf Taschner zu Wort kommen lassen. Er ist Mathematiker und Hauptfigur im Projekt "mathspace". Schöner und übersichtlicher kann man die Entwicklung unseres Kalenders kaum beschreiben.
Die Julianische Tageszahl
In meinem privaten Umfeld kam ich bei meiner Ahnenforschung schnell an die Grenzen der gängigen Darstellung des Kalenderdatums. Die Betriebssysteme z.B. zählen die Sekunden seit 1.1.1970. Ich bin 1963 geboren. Dieses Datum kann ich also schon nicht mehr mit gängigen Boardmitteln des Betriebssystems darstellen; was erst recht für meine Ahnen gilt ;-) Auf der Suche nach einer Lösung kam ich schnell auf Algorithmen, die zwischen einem gegebenen Datum und der Julianischen Tageszahl wandeln.
Die Julianische Tageszahl bezeichnet einen Zeitstrahl gemessen in Tagen beginnend mit dem 1.1.4713 vor Christus. Hier der erste Algorithmus, mit dem ich in Kontakt kam. Er wandelt das Datum bestehend aus Tag, Monat, Jahr in die Julianische Tageszahl um. Gerechnet wird mit der Schaltjahresrechnung des Gregorianischen Kalenders, der am 4. Oktober 1582 eingeführt wurde und seit dem gültig ist.
[1] if month <= 2 then
[2] month = month + 12
[3] year = year - 1
[4] endif
[5] b = (int)(year/400) - (int)(year/100) + (int)(year/4)
[6] a = 365.0*year + 1720997;
[7] jd0 = a + b + (int)(30.6001*(month+1)) + day
Bevor der Januar zum ersten Monat des Jahres erklärt wurde, begann das Jahr mit dem Monat März. Das kann man unter anderem daran erkennen, dass die Monate Oktober, November und Dezember die 8, 9 und 10 in ihrem Namen tragen. Damit stand der Februar als Monat mit dem Schalttag am Ende des Jahres. Das war sehr viel praktischer bei jeglichen Kalenderberechungen. In der Zeile [1] bis [4] unseres Algorithmus wird der Januar zum 13. und der Februar zum 14. Monat des vorhergehenden Jahres.
Unser Kalenderjahr richtet sich nach der Sonne aus und dauert fast genau so lange, wie eine Umrundung der Erde um die Sonne. Das sind 365,2422 Tage. Der Tag des Gregorianischen Kalenders ist 365,2425 Tage lang. Den noch verbleibenden Unterschied von 0,0003 Tagen wird mit Schaltsekunden korrigiert und ist für unsere Betrachtungen nicht relevant. In der Zeile [5] werden die Schalttage seit der Zeitenwende berechnet.
Ein Jahr ohne Schalttag hat 365 Tage. In Zeile [6] werden die Tage in Gemeinjahren, d.h. ohne Schalttage seit der Zeitenwende zu dem Julianischen Tag der Zeitenwende addiert. Wobei hier eine Differenz zum tatsächlichen Julianischen Tag der Zeitenwende existiert. [???] Dies erklärt sich damit, dass das aktuelle Jahr multipliziert wird und die Schalttage keine Beachtung finden, da sie in Zeile [5] schon berechnet werden.
In Zeile [7] wird ein Algorithmus verwendet, der mich immer wieder fasziniert. Die Monate beginnend mit dem März haben folgende Reihe ihrer Längen. März (31), April (30), Mai (31), Juni (30), Juli (31), August (31), September (30), Oktober (31), November (30), Dezember (31), Januar (31), Februar (der Rest): 31 30 31 30 31 | 31 30 31 30 31 | 31 Rest. Jetzt wird klar, dass es hier eine Zahl braucht, mit der man den Monat multiplizieren kann und die eine solche Folge produziert: 30.6001 hat ein kluger Kopf gefunden. Zu dieser Konstante wird der Monat um eins erhöht addiert; erinnern wir uns doch daran, dass in Zeile [1] bis [4] der Anfang des Jahres auf März verschoben wird. Deshalb zählen die Monate 3 = März bis 14 = Februar. In Zeile [7] werden dann noch die Ergebnisse aus Zeile [5] und Zeile [6] zuaddiert. Damit ist die Julianische Tageszahl errechnet-
Dieser Algorithmus ist nur gültig seit der Gregorianschen Kalenderreform 1582. Für die Zeit davor gilt der Julianische Kalender, für den wir später die entsprechenden Algorithmen kennen lernen dürfen.
Der folgende Algorithmus tut das Gegenteil von unserem ersten; er wandelt von der Julianischen Tageszahl zurück in Tag, Monat und Jahr. Diesen Algorithmus zu verstehen brauche ich noch einige Momente absoluter Konzentration ;-)
[1] b = (int)((jd0-1867216.25)/36524.25);
[2] c = jd0 + (b-(int)(b/4)) + 1525.0;
[3] d = (int)((c-122.1)/365.25);
[4] e = 365.0 * d + (int)(d/4);
[5] f = (int)((c-e)/30.6001);
[6] day = (int)((int)(c-e+0.5) - (int)(30.6001*f));
[7] month = (int)(f - 1 - 12*(int)(f/14));
[8] year = (int)(d - 4715 - (int)((7+month)/10));