Kalenderwoche berechnen
Nennt zu jedem Datum die Kalenderwoche nach ISO 8601 — und umgekehrt zu jeder Woche ihren Montag und Sonntag.
„Das machen wir in KW 37" — der Satz fällt in Betrieben täglich, und regelmäßig sucht dann jemand einen Kalender. Dieses Script beantwortet beide Fragen: In welche Kalenderwoche fällt ein bestimmtes Datum, und welche Tage umfasst eine bestimmte Kalenderwoche?
Gerechnet wird nach ISO 8601, der internationalen Norm, die in Europa gilt. Ihre Regel klingt zunächst umständlich und ist bei näherem Hinsehen elegant: Die Woche beginnt am Montag, und die erste Kalenderwoche eines Jahres ist diejenige, die den ersten Donnerstag enthält. Gleichbedeutend damit: Es ist die Woche, in der der 4. Januar liegt, oder auch: die erste Woche mit mindestens vier Tagen im neuen Jahr.
Daraus folgt etwas, das viele überrascht: Der 1. Januar gehört nicht immer zur KW 1. Fällt er auf einen Freitag, Samstag oder Sonntag, zählt er noch zur letzten Woche des Vorjahres — dann hat der 1. Januar die Kalenderwoche 52 oder 53. Umgekehrt können die letzten Dezembertage schon zur KW 1 des Folgejahres gehören. Das Script zeigt deshalb immer auch das sogenannte Wochenjahr an, das vom Kalenderjahr abweichen kann.
Und noch eine Besonderheit: Die meisten Jahre haben 52 Kalenderwochen, manche aber 53. Auch das rechnet euch das Script aus. In den USA und einigen anderen Ländern gilt übrigens eine andere Zählung — dort beginnt die Woche am Sonntag und die KW 1 ist schlicht die mit dem 1. Januar. Wer mit internationalen Partnern arbeitet, sollte das im Hinterkopf behalten.
Verwandtes: der Kalender zum Blättern, Tage zwischen zwei Daten und Arbeitstage berechnen.
Gerechnet wird nach ISO 8601: Die Woche beginnt am Montag, KW 1 ist die Woche mit dem ersten Donnerstag.
So funktioniert das Script
Die Wochenberechnung gilt als Klassiker unter den kniffligen Datumsaufgaben. Der Trick, mit dem sie einfach wird, steckt in einer einzigen Zeile.
const wochentag = d.getUTCDay() === 0 ? 7 : d.getUTCDay();
d.setUTCDate(d.getUTCDate() + 4 - wochentag);
Statt das gegebene Datum zu betrachten, springt das Script erst einmal auf den Donnerstag derselben Woche. Der Grund: Nach ISO 8601 gehört eine Woche zu dem Jahr, in dem ihr Donnerstag liegt — er ist der mittlere Tag der Fünftagewoche und entscheidet damit alles. Hat man ihn, sind alle Sonderfälle um den Jahreswechsel von selbst erledigt.
Die erste Zeile korrigiert dabei eine Eigenheit von JavaScript: getUTCDay() liefert den Sonntag als 0 und den Montag als 1. Die Norm zählt aber den Montag als 1 und den Sonntag als 7. Die Umrechnung ist eine Zeile — sie zu vergessen ist der häufigste Fehler bei dieser Aufgabe, und zwar einer, der nur an Sonntagen auffällt.
const jahresanfang = new Date(Date.UTC(wochenjahr, 0, 1));
const tage = (d - jahresanfang) / 86400000;
return { woche: Math.floor(tage / 7) + 1, jahr: wochenjahr };
Jetzt wird nur noch gezählt, der wievielte Donnerstag des Jahres es ist. Zwei Date-Objekte lassen sich voneinander abziehen; heraus kommt der Abstand in Millisekunden. 86400000 ist die Anzahl der Millisekunden eines Tages (24 · 60 · 60 · 1000), und geteilt durch 7 ergibt sich die Woche.
new Date(Date.UTC(jahr, monat, tag))
Alle Rechnungen laufen bewusst in UTC, der koordinierten Weltzeit. Der Grund ist die Sommerzeit: Rechnet man in Ortszeit, sind manche Tage 23 und andere 25 Stunden lang, und die Division durch die Millisekunden eines Tages liefert dann krumme Werte, die beim Abrunden gelegentlich einen Tag danebenliegen. In UTC gibt es keine Zeitumstellung, deshalb ist jeder Tag exakt gleich lang. Der Preis ist, dass auch die Ausgabe mit timeZone: "UTC" erfolgen muss — sonst verschöbe der Browser die Anzeige wieder in die Ortszeit.
const vierter = new Date(Date.UTC(jahr, 0, 4));
montag.setUTCDate(vierter.getUTCDate() - wochentag + 1 + (woche - 1) * 7);
Für den umgekehrten Weg dient der 4. Januar als Anker, denn er liegt nach der Norm garantiert in der KW 1. Von ihm aus geht es zum Montag seiner Woche zurück und dann in Siebenerschritten vorwärts. Beachtet, dass setUTCDate auch mit Werten unter 1 oder über der Monatslänge umgehen kann: setUTCDate(-3) landet im Vormonat, setUTCDate(40) im nächsten. Diese Nachsicht erspart einem sämtliche Monats- und Jahresübergänge von Hand.
function wochenImJahr(jahr) {
return wocheUndJahr(jahr, 11, 28).woche;
}
Ein hübscher Kniff zum Schluss: Um zu erfahren, ob ein Jahr 52 oder 53 Wochen hat, fragt man einfach nach der Kalenderwoche des 28. Dezember. Dieser Tag liegt nach der Norm immer in der letzten Woche seines Jahres — genau wie der 4. Januar immer in der ersten liegt.
Zum Anpassen: Für die amerikanische Zählung, bei der die Woche am Sonntag beginnt und die KW 1 die Woche mit dem 1. Januar ist, wird die Rechnung tatsächlich einfacher: Tage seit dem 1. Januar durch sieben, aufgerundet. Nur passt das Ergebnis dann nicht zu dem, was hierzulande in Terminplanern steht.
Script für die eigene Homepage
Kopiert euch den kompletten Code und fügt ihn an der Stelle eurer Seite ein, an der das Script erscheinen soll. Er läuft ohne weitere Dateien und ohne fremde Server.
Mehr aus der Kategorie Datum & Uhrzeit
-
An welchem Wochentag wurde ich geboren?
-
Analoge Uhr
-
Analoge Uhr mit römischen Ziffern
-
Arbeitstage berechnen
-
Chinesisches Tierkreiszeichen
-
Digitaluhr
-
Jahreszeit
-
Kalender
-
Kalender mit Uhrzeit und Feiertagen
-
Mondphase berechnen
-
Osterdatum berechnen
-
Schaltjahr prüfen
-
Sternzeichen ermitteln
-
Tage bis zum Jahr 3000
-
Tage zwischen zwei Daten
-
Uhrzeit in Worten
-
Unix-Zeitstempel wandeln
-
Weltzeituhr
-
Zeitumstellung