Christian Seiler: Noch eine weitere Falle?

Beitrag lesen

Hallo Tom,

Andererseits ist zumindest die ganze Diskussion um andere Kalender ziemlich irrelevant für diese Fragestellung, da hier ja eine Frage gestellt wurde, die ganz klar auf den hiesigen Kalender gemünzt war.

Wenn man eine "universelle" Funktion baut, müsste man aber trotzdem darüber machdenken.

Ich hatte sowas mal angefangen: </archiv/2006/9/t137256/#m891605>

Ich hatte nämlich vorhin nur mal so aus Spaß angefangen, das von der Basis her aufzubauen, also ganz ohne die Kalenderfunktionen. Da fängt es schon an, dass man irgendwo einen Referenztag haben muss (also wie Unix das z.B. mit dem 01.01.1970 macht. Von dem muss man eben wissen, welcher Wochentag dazugehörte...

Mein Vorschlag ist und bleibt die julianische Tageszahl, d.h. die Anzahl an Tage seit dem 1.1.4713 v.u.Z. JC (das war ein Montag). Algorithmen zur Konvertierung findest Du in meiner Klassensammlung bzw. inzwischen effizientere Versionen in meinen Postings hier im Thread bzw. hier im Thread verlinkt.

Und dann kommen die Fragen zu Schaltjahr und wieviele Wochen hat das Jahr.
Ok, dafür gibt es logische Bedingungen.

Normales Jahr: Wenn der 04. Januar ein Do ist, hat das Jahr 53KWs
Schaltjahr:    Wenn der 04. Januar ein Mi oder ein Do ist, hat das Jahr 53KWs

Wie viele Wochen ein Jahr hat, ist irrelevant für fast alle Berechnungen. Wichtig ist: Wann fängt ein Jahr an? Das ist die einzig nötige Information sowohl für das Hin- als auch das Rückrechnen.

Ok, erstmal noch allgemeine Infos: Wir reden hier über Kalenderwochen nach ISO8601 (wenn jemand was anderes meint, müsste er erstmal definieren, was er will). Das heißt: Der zugrundeliegende Kalender ist gregorianisch - auch proleptisch, d.h. sogar VOR 15. Oktober 1582 gültig - auch wenn's ihn damals noch nicht gab.

Wie ist nun der Jahres-Wochenkalender in ISO8601 definiert? Die Jahre orientieren sich an den Jahren des gregorianischen Kalenders, sind aber an Wochen ausgerichtet. Die erste Woche ergibt sich durch die Woche, die den 4. Januar enthält, das Jahr fängt immer am Montag an (damit fangen einige Kalenderwochen-Jahre z.B. auch am 31. Dezember des vorigen "normalen" Jahres an) und hat 52 oder 53 Wochen, was sich nach dem Jahresanfang des nächsten Jahres richtet. Zur Unterscheidung nenne ich mal die Wochen-Jahreszahl im folgenden "WJahr" und die normale Jahreszahl "Jahr".

Nun zu dem allgemeinen Verfahren wie man (Jahr, Monat, Tag) in (WJahr, Woche, Wochentag) umrechnet. Im folgenden werde ich das ganze mit Pseudocode erklären, folgende Funktionen existieren:

* DatumZuKontinuierlich (Jahr, Monat, Tag)
   Wandelt das Datum in eine kontinuierliche Tageszählung um, d.h. irgend
   eine Zählung, die die Anzahl an Tagen ab einem Referenzdatum angibt.

* KontinuierlichZuDatum (Zahl)
   Wandelt ein Datum in kontinuierlicher Tageszählung in ein normales
   Datum um.

* Wochentag (Zahl)
   Gibt den Wochentag eines Datums in kontinuierlicher Tageszählung an,
   dabei 0 = Montag, 1 = Dienstag, ..., 6 = Sonntag

Wie wandelst Du nun ein Datum (Jahr, Monat, Tag) in (WJahr, Woche, Wochentag) um?

TAG_ZAHL = DatumZuKontinuierlich (Jahr, Monat, Tag)
JAHR_ANFANG = DatumZuKontinuierlich (Jahr, 1, 4)
JAHR_ANFANG = JAHR_ANFANG - Wochentag (JAHR_ANFANG)
WENN (TAG_ZAHL < JAHR_ANFANG):
   JAHR_ANFANG = DatumZuKontinuierlich (Jahr - 1, 1, 4)
   JAHR_ANFANG = JAHR_ANFANG - Wochentag (JAHR_ANFANG)
   WJahr = Jahr - 1
SONST:
   WJahr = Jahr
Woche = ABRUNDEN ((TAG_ZAHL - JAHR_ANFANG) / 7) + 1
Wochentag = Wochentag (TAG_ZAHL)

Wir haben (WJahr, Woche, Wochentag)

Wie wandelst Du ein Datum (WJahr, Woche, Wochetag) in (Jahr, Montag, Tag) um?

JAHR_ANFANG = DatumZuKontinuierlich (WJahr, 1, 4)
JAHR_ANFANG = JAHR_ANFANG - Wochentag (JAHR_ANFANG)
TAG_ZAHL = JAHR_ANFANG + (Woche - 1) * 7 + Wochentag
(Jahr, Monat, Tag) = KontinuierlichZuDatum (TAG_ZAHL)

Sprich: Mit dem Jahresanfang kommst Du wunderbar aus, die Anzahl an Wochen in einem Jahr interessieren Dich für die Berechnung von Kalenderwochen nach ISO8601 erst einmal nicht. Wenn Du aber doch die Anzahl an Wochen wissen willst, kannst Du das so machen (gegeben sei Jahr):

JAHR_ANFANG = DatumZuKontinuierlich (Jahr, 1, 4)
JAHR_ANFANG = JAHR_ANFANG - Wochentag (JAHR_ANFANG)
NJAHR_ANFANG = DatumZuKontinuierlich (Jahr + 1, 1, 4)
NJAHR_ANFANG = NJAHR_ANFANG - Wochentag (NJAHR_ANFANG)
WochenImJahr = (NJAHR_ANFANG - JAHR_ANFANG) / 7

Und was war mit dem Jahr, als der Gregorianische Kalender eingeführt wurde?

Als der gregorianische Kalender _WO_ eingeführt wurde? ;-) Im Vatikan wurde er offiziell 1582 eingeführt und die Griechen haben im irgendwann um 1920 herum umgestellt.

Viele Grüße,
Christian