Kalenderwoche

Die Wochen eines Jahres von 1-53

Mindestens seit dem Altertum werden die Tage in 7-Tage-Wochen gezählt, selbst Katastrophen, Kriege und Kalender-Reformen haben diesen Zyklus nicht unterbrochen.
Nur in wenigen Kulturen wurden Wochen anderer Länge verwendet.
In der Wirtschaft wird die Kalenderwoche (KW) häufig zur Angabe von Terminen verwendet.
Leider ist es möglich, die Kalenderwochen eines Jahres unterschiedlich zu zählen.
In der EU gilt dafür der weltweite Standard ISO-8601.
Alle Angaben dieser Seite ohne Gewähr !
Die Verwendung von Daten und Algorithmen erfolgt auf eigenes Risiko !
Datum & Zeit Schnittpunkt von uralter Kultur und Informationstechnik
Live-Test Algorithmus mit Live-Test
Standards und Algorithmen (Rechen-Vorschriften)
Kalenderwoche nach ISO-Standard
US-Kalenderwoche
Andere Definitionen der Kalenderwoche
Software Die KW in Standard Büro-Software
Entwicklung Die KW mit Javascript, PHP, Perl, VBA

Live-Test der Kalenderwoche

  Jahr
  Monat
  Tag

0
Heute
Datum
0000-00-00
Wochentag
Wochentag
ISO-Woche
  Referenztag
0000-00-00
  Differenz-Tage
0
  ISO-KW
0
  ISO-String
0000-W00
US-Woche
  Referenztag
0000-00-00
  Differenz-Tage
0
  US-KW
0

Kalenderwoche nach ISO-8601

Heute ist Wochentag, 0000-00-00, dieser Tag liegt in ISO-Kalenderwoche 0000-W00
Der Standard ISO-8601 definiert die Kalenderwoche mit 3 Regeln:

ISO-8601 Regeln (EU):

Alle Kalenderwochen beginnen am Montag.
Es gibt nur ganze Wochen, keine Wochen-Fragmente.
Die erste Kalenderwoche eines Jahres ist jene Woche, in welche mindestens 4 der ersten 7 Jänner-Tage fallen.
Daraus ergibt sich: Der 4. Jänner liegt immer in KW1
Die meisten Jahre (82%) umfassen KW1 bis KW52, einige Jahre (18%) bis KW53.

Die Angabe der Kalenderwoche in Texten (Zeichenketten, Strings) erfolgt nach ISO-8601 immer 2stellig, wobei das Jahr und die Zeichen '-W' vorangestellt werden, z.B. für heute
0000-W00

ISO-Algorithmus (Rechen-Vorschrift)

mit den Live-Daten des heutigen Datums.

Referenz-Tag
(1) Suche den Referenz-Tag, d.h. jenen Montag, mit dem W01 des gesuchten Jahres beginnt.

(1.1) Bestimme die Wochentags-Nummer dow am 4. Jänner des gesuchten Jahres mit dow=1..7 für Mo..So.
dow(0000-01-04) = 0 (Wochentag)

(1.2) Der Referenz-Tag dieses Jahres liegt um (dow-1) Tage vor dem 4. Jänner und muss immer ein Montag sein. Heuer ist
dref(0000) = 0000-00-00 (Montag)
Anmerkung: Wenn dow>4 dann liegt der Referenz-Tag im Vorjahr, das ändert nichts an der Berechnung.
→ Weiter mit (2).

Details zur Bestimmung des Wochentages:
Datum & Zeit (allgemein), Javascript, Perl, PHP, VBA.

Mit dem ↑ Live-Test am Anfang dieser Seite können sie die Kalenderwoche beliebiger Daten berechnen.
Differenz
(2) Berechne die Kalenderwoche aus dem Abstand zwischen dem gesuchten Datum und dem Referenz-Tag.

(2.1) Bestimme die Differenz d_tage zwischen dem gesuchten Datum und dem Referenztag in ganzen Tagen.
d_tage(0000-00-00 - 0000-00-00) = 0

Bedingte Verzweigung
(2.2) Je nach Zahlenwert von d_tage wird einer von 3 Fällen ausgewählt:
Wenn d_tage>=0 UND d_tage<359 dann wird die ISO-Kalenderwoche mit → (2.3) fertig berechnet. Dieser Fall tritt am häufigsten auf.
Wenn d_tage<0 dann liegt der gesuchte Tag vor dem Referenz-Tag am Jahres-Anfang. In diesem Fall weiter mit → (3).
Wenn d_tage>=359 dann muss überprüft werden, ob der gesuchte Tag bereits in KW1 des nächsten Jahres fällt. In diesem Fall weiter mit → (4).

Abschluss
(2.3) Berechnung der ISO-Kalenderwoche:
Die Differenz d_tage wird durch 7 (Tage pro Woche) dividiert, die Nachkomma-Stellen abgeschnitten. Danach wird 1 addiert, da der Referenz-Tag selbst bereits in KW=1 liegt.
kw = floor(d_tage/7)+1 = floor(0.00)+1 = 0
Damit ist die ISO-Woche fertig berechnet.
(3) Jahres-Anfang
Wenn d_tage<0 dann wird der Referenz-Tag des Vorjahres verwendet.
Dieser Fall tritt durchschnittlich nur bei 1.6% aller Fälle auf - Da man die KW für Feiertage (Neujahrstag) selten bestimmt, nur in 0.8% aller Fälle.
Dieser Fall trifft für heute nicht zu.

(3.1) Bestimme die Wochentags-Nummer am 4. Jänner des Vorjahres
dow(0000-01-04) = 0 (Wochentag)

(3.2) Der Referenz-Tag des Vorjahres wird analog zu (1.2) berechnet:
dref(0000) = 0000-00-00 (Montag)
Dann wird der Algorithmus mit → (2.1) weiter verfolgt:
d_tage(0000-00-00 - 0000-00-00) = 0
In diesem Fall ergibt sich immer eine positive Differenz d_tage>0.
Die Berechnung wird mit → (2.3) fortgesetzt und beendet.
(4) Jahres-Ende
Wenn d_tage>=359 dann wird probeweise der Referenz-Tag des Folgejahres berechnet. Dieser Fall erfordert den meisten Aufwand, kommt aber zum Glück nur selten vor.
Dieser Fall trifft für heute nicht zu.

(4.1) Bestimme die Wochentags-Nummer am 4. Jänner des Folgejahres
dow(0000-01-04) = 0 (Wochentag)

(4.2) Der Referenz-Tag des Folgejahres wird analog zu (1.2) berechnet:
dref(0000) = 0000-00-00 (Montag)
Die Anzahl der Differenz-Tage d_test wird in diesem Fall nur probeweise berechnet:
d_test(0000-00-00 - 0000-00-00) = 0

(4.3) Bedingte Verzweigung:
Wenn d_test>=0 dann fällt der Tag in KW1 des Folgejahres.
In diesem Fall wird d_tage=d_test gesetzt.
Wenn d_test<0 dann erfolgt keine Änderung.
Die Berechnung mit → 2.3) fortgesetzt und beendet.

US-Kalenderwoche

US-Regeln

Alle ganzen Kalenderwochen beginnen am Sonntag.
Am Beginn und am Ende jedes Jahres werden verkürzte Teil-Wochen zugelassen.
Die erste Kalenderwoche beginnt am 1. Jänner jedes Jahres, und zwar auch dann, wenn dieser Tag nicht auf einen Sonntag fällt.

Nach diesen Regeln ergibt sich keine einzige Übereinstimmung zwischen ISO-KW und US-KW.
Wenn man jedoch von Sonntag absieht, dann ergeben die Regeln für Werktage in ca. 57% aller Jahre die gleiche KW, in 43% eine andere.
Die nächsten halbwegs übereinstimmenden Jahre sind 2006-2008, 2012-2014, 2017-2020, ..

US-Algorithmus:

(1.1) Bestimme die Wochentags-Nummer am 1.Jänner des gesuchten Jahres mit dowu=0..6 für So..Sa.
dowu(0000-01-01) = 0 (Wochentag)

(1.2) Der Referenz-Tag dieses Jahres liegt um dowu Tage vor dem 1. Jänner. Heuer ist
dref(0000) = 0000-00-00 (Sonntag)
Anmerkung: Der Referenz-Tag kann auch im Vorjahr liegen, das ändert nichts an der Berechnung.

(2.1) Bestimme die Differenz d_tage zwischen dem gesuchten Datum und dem Referenztag in ganzen Tagen.
d_tage(0000-00-00 - 0000-00-00) = 0

(2.2) Die Kalenderwoche ergibt sich nach Division durch 7 und Abschneiden der Nachkomma-Stellen. Danach wird 1 addiert, da der Referenz-Tag selbst bereits in KW=1 liegt.
kw = floor(d_tage/7)+1 = floor(0.00)+1 = 0
Damit ist die US-Woche fertig berechnet.
Am Jahresende gibt es meist auch dann Differenzen zur ISO-Woche, wenn die Werktage des betreffenden Jahres übereinstimmen:
Nach ISO-Regel können die Tage 29. Dez . . 31. Dez bereits in KW1 des nächsten Jahres fallen, nach US-Regel wird das Jahr mit einer allenfalls verkürzten Teil-Woche beendet.
Nach US-Regeln ergeben sich daher ca. alle 7 Jahre am 31. Dezember 1-Tages-Wochen. In seltenen Fällen erhalten diese den Wert KW54, z.B. am 2000-12-31 oder 2028-12-31.
Die Unterschiede zwischen ISO-KW und US-KW sind wenig bekannt, nicht notwendig und können viel Geld kosten.
Vorsicht - US-Software neigt dazu, ungefragt die US-Regeln zu verwenden.

Verwenden sie daher im Zweifel immer das exakte → ISO-Datum an Stelle der Kalenderwoche und überlassen sie es anderen PC, daraus bei Bedarf die lokale Kalenderwoche zu berechnen.

Non-Standard: Andere Definitionen der Kalenderwoche (week of year, woy)

Staaten:

Die Kalenderwoche nach ISO-Standard gilt in der EU und in den meisten Staaten der Welt. In den USA, aber auch in einigen 'neuen' Beitrittsländern der EU gelten abweichende Regeln.

Falls sie in Geschäftsbeziehungen mit anderen Staaten die KW angeben, recherchieren sie vorher unbedingt, ob die ISO-KW gilt, oder welche anderen Regeln angewendet werden.

Insbesondere bei den 'neuen' EU-Mitgliedern ist damit zu rechnen, dass abweichende Regeln in nächster Zeit durch die ISO-KW ersetzt werden.

Falls sie die zutreffenden KW-Regeln nicht kennen, geben sie sicherheitshalber das → ISO-Datum (von..bis) an Stelle der KW an.

Abweichende Regeln:


Teil-Wochen am Jahreswechsel:
Wenn der Jahreswechsel nicht mit dem Wochen-Wechsel zusammenfällt, dann werden am Anfang und Ende des Jahres verkürzte Teil-Wochen eingefügt. Die Definition von Jahreswechsel ist weltweit eindeutig, diejenige von Wochen-Wechsel jedoch nicht !

Wochenbeginn am Sonntag:
In den USA beginnt die Woche am Sonntag und endet am Samstag. Das scheint mit einer Berufung auf die Bibel zusammenzuhängen. Die Nummerierung von US-Wochentagen ist nicht einheitlich, Versionen 0..6 und 1..7 für So..Sa sind in Gebrauch.

KW54:
Nach ISO-Regeln sind nur maximal 52 oder 53 (ganze) KW möglich. Nach US-Regeln ergibt sich selten eine 1-tägige (!) US-KW54, z.B. am 2000-12-31 und 2028-12-31

Wochenbeginn am ersten Sonntag des Jahres:
In diesem Fall ergeben sich vor Beginn von KW1 je nach Wochentag 0..6 Tage, welche in KW52..KW53 des Vorjahres fallen. Diese Regel ist nur mit ungeteilten Wochen sinnvoll.
Beispiele:
So-Woche(2003-01-06)=1
nach ISO ist KW(2003-01-06)=2

Wochenbeginn am ersten Montag des Jahres:
In diesem Fall ergeben sich vor Beginn von KW1 je nach Wochentag 0..6 Tage, welche in KW52..KW53 des Vorjahres fallen. Diese Regel ist nur mit ungeteilten Wochen sinnvoll.
Beispiele:
Mo-Woche(2004-01-05)=1
nach ISO ist KW(2004-01-05)=2

Standard Büro-Software

Software:

Verwenden sie nie die KW-Berechnung von Programmen ohne sorgfältigen Test und/oder Garantie des Herstellers.

Wenn sie Tests ausführen (Kalender, Live-Test auf dieser Seite, ...), dann prüfen sie vor allem die ersten und letzten Tage mehrerer Jahre - Dort zeigen sich auch dann Abweichungen, wenn die KW-Berechnung anderer Tage zufällig übereinstimmt.
Die Standard Büro-Programme LibreOffice und OpenOffice liefern die korrekte ISO-Kalenderwoche mit der Funktion
=KALENDERWOCHE(datum;2)
Die US-Kalenderwoche wird mit dieser Funktion berechnet:
=KALENDERWOCHE_ADD(datum;1)
Die professionellen Office-Pakete LibreOffice und OpenOffice sind kosten- und lizenzfrei für alle gängigen Betriebssysteme und Sprachen verfügbar und voll kompatibel mit dem Office-Paket des IT-Marktführers.
Das Kalkulations-Programm MS-Excel bietet die Funktion 'Kalenderwoche'.
Diese Funktion rechnet (derzeit) in keinem Fall nach ISO-Norm.

Erstaunlich, wie wenig Aufmerksamkeit die KundInnen eines ganzen Kontinents erhalten - Trotz der großzügigen öffentlichen Förderung für M$-Software ("PC-Führerschein").

Optional können sie VBA-Funktionen (nächster Absatz) in Form eines ↓ AddIn oder eines importierten ↓ VBA-Moduls dafür einsetzen.
Die Excel-Funktion Kalenderwoche
Diese Funktion ist in der Excel-Grundversion normalerweise nicht enthalten. Sie ist in Europa unbrauchbar.
Man kann die Funktion mit dem AddIn 'Analyse-Funktionen' laden.
Sie verwendet als 1.Argument ein Datum im üblichen Y1900-Format.
Als 2. Argument kann man eine Option "Rückgabe" angeben, für die es keine Hilfe gibt - wohl kein Zufall.
Ohne 'Rückgabe' oder mit 'Rückgabe=1' wird die US-Kalenderwoche berechnet.
Mit 'Rückgabe=2' wird eine unbekannte KW mit Beginn an Montagen berechnet, jedoch nicht nach ISO-Regeln !

AddIn  kalenderwoche.xla


Das AddIn enthält die beiden Funktionen kalenderwoche_iso() und kalenderwoche_us()
Die Anwendung ist kostenlos und unverbindlich, erfolgt jedoch auf eigenes Risiko.

Die folgenden Angaben gelten sinngemäß für alle AddIn-Module:
(In die Pfade wurden Leerzeichen eingefügt, um sie trotz ihrer Länge hier anzuzeigen)

Um das AddIn für alle AnwenderInnen zu laden, kopieren sie es hierher:
C: \ Programme \ Microsoft Office \ Office* \ Makro \ kalenderwoche.xla
(Ersetzen sie * durch ihre Office Versions-Nr.).

Um das AddIn für einzelne AnwenderInnen zu laden, kopieren sie es hierher:
C: \ Dokumente und Einstellungen \ * \ Anwendungsdaten \ Microsoft \ Excel \ XLStart \ kalenderwoche.xla
(Ersetzen sie * durch den User-Namen.).

Suchen sie die Addin-Funktionen im Menü Einfügen | Funktion | Kategorie = Benutzerdefiniert. Je nach Version sind die Funktionen bereits verfügbar. Wenn nicht, muss das Addin mit Extras | AddIns aktiviert werden. Falls das AddIn in der Liste nicht aufscheint, klicken sie Durchsuchen..

Die Addin-Funktionen können nun verwendet werden.
Leider wird keine einzige Benutzerdefinierte Funktion von M$ für würdig befunden, in der Kategorie "Zuletzt verwendet" aufzuscheinen.

AddIns sind - falls aktiviert - immer (in jedem Excel-Dokument) verfügbar, man muss sich nicht mehr darum kümmern. Der Komfort hat aber auch Nachteile:

Bei Weitergabe von Excel-Dokumenten sind die AddIn-Funktionen darin nicht enthalten. Nur wenn auch das AddIn weitergegeben wird, können seine Funktionen weiterhin berechnet werden.

Die einzige Möglichkeit, zusätzliche Funktionen zusammen mit einem Excel-Dokument zu speichern, ist ein importiertes oder selbst erstelltes VBA-Modul. (nächster Absatz)

Download des AddIn kalenderwoche.xla (24 kB)
Details zum Thema VBA @ Module

Import-Modul   kalenderwoche.bas


Das Import-Modul enthält die gleichen Funktionen wie das AddIn (Absatz oben).

Ein Import-Modul muss in jedes einzelne Dokument geladen werden, in dem es gebraucht wird.
Dieses Verfahren ist wesentlich umständlicher als die Verwendung eines AddIn, hat aber Vorteile bei der Weitergabe von Dokumenten.

Speichern sie die Modul-Datei in einem beliebigen Pfad, z.B.
C: \ Programme \ Microsoft Office \ Office* \ Makro \ kalenderwoche.bas
Der Pfad sollte allen AnwenderInnen bekannt sein.

Laden eines Import-Moduls:
Öffnen sie ein Excel-Dokument und wechseln sie zum VBA-Fenster: Tasten Alt-F11 oder Menü Extras | Makro | Visual Basic Editor
Importieren sie das Modul kalenderwoche.bas mit Datei | Datei importieren

Speichern sie das Excel-Dokument.
Die Funktionen des Moduls sind jetzt auf jedem Arbeitsblatt dieses Dokuments verwendbar.

Das Excel-Dokument enthält nun seine eigene Kopie der Funktionen. Sie bleiben enthalten, wenn das Dokument weitergegeben wird. Das VBA-Modul braucht man daher (im Gegensatz zu einem AddIn) nicht an entfernte AnwenderInnen weitergeben.

Allerdings ist es möglich, die VBA-Funktionen zu manipulieren, und damit falsche Resultate zu berechnen. Um das auszuschließen, sollten sie das VBA-Modul schützen:
Wechseln sie mit Alt-F11 in das VBA-Fenster und sichern sie mit Extras | Eigenschaften | Schutz
Aktivieren sie "Projekt für die Anzeige sperren" und geben sie ein Kennwort ein.

Download des Moduls kalenderwoche.bas (2 kB)
Details zum Thema VBA @ Module

Entwicklung

Javascript

Die Funktion woy_iso() des Beispiels berechnet die ISO-Kalenderwoche.
Die Variable utsd enthält einen → UNIX-Timestamp (im ms) des untersuchten Datums d
Das Referenz-Datum des Jahres yy wird mit Hilfsfunktion dref_iso() berechnet und getestet.
Wenn das gesuchte Datum davor liegt (dif<0), wird das Referenz-Datum des Vorjahrs yy-1 herangezogen.
Wenn das gesuchte Datum am Jahresende liegt, wird geprüft, ob es in KW1 des Folgejahres yy+1 fällt.
Zuletzt wird die ISO-Woche aus der Differenz dif zum Referenz-Datum berechnet und zurückgegeben. Der Faktor 604800000 ergibt sich aus 7*24*60*60*1000, der Faktor 86400000 aus 24*60*60*1000

Die Funktion woy_us() berechnet auf ähnliche Weise die US-Kalenderwoche.
Da die Hilfsfunktion dref_us() (berechnet einen Timestamp des US-Referenz-Datums) nur einmal verwendet wird, kann man sie auch direkt in woy_us() integrieren.

Details zum Thema Javascript @ Datum & Zeit
function woy_iso(d) {
var utsd=d.getTime();
var yy=d.getUTCFullYear();
var dif=utsd-dref_iso(yy);
if(dif<0) {
dif=utsd-dref_iso(yy-1);
}
else if(dif>358) {
var dif$=utsd-dref_iso(yy+1);
if(dif$>=0) {dif=dif$;}
}
return Math.floor(dif/604800000)+1;
}

function dref_iso(yy) {
var uts=Date.UTC(yy,0,4);
var dow=new Date(uts).getDay();
if(dow==0) {dow+=7;}
return uts-(dow-1)*86400000;
}

function woy_us(d) {
var utsd=d.getTime();
var dif=utsd-dref_us(d.getUTCFullYear());
return Math.floor(dif/604800000)+1;
}

function dref_us(yy) {
var uts=Date.UTC(yy,0,1);
var dow=new Date(uts).getDay();
return uts-dow*86400000;
}

Perl

Die Posix-Funktion strftime() gibt mit Platzhalter %V die ISO-Kalenderwoche aus, mit %U die US-Kalenderwoche. Als Argument wird ein → UNIX-Timestamp verwendet.
Die Funktion gibt einen Ziffern-Text (String) zurück, der bei Bedarf durch Addition von Null in eine ganze Zahl umgewandelt wird.
Das Modul POSIX ist normalerweise in jeder Perl-Distribution enthalten, muss jedoch vor Verwendung ausdrücklich angefordert werden.

Das Modul Date::Calc bietet die Funktion Week_of_Year(), die zwar nicht exakt dokumentiert ist, jedoch zumindest auf mitteleuropäischen Betriebssystemen offenbar die ISO-Kalenderwoche liefert.

Details zu Perl @ Datum und Zeit, Perl-Module

POSIX-Funktion srtrftime()
use POSIX;
$uts = time();
$iso_kw = strftime("%V",$uts)+0;
$us_woy = strftime("%U",$uts)+0;
print "ISO-KW=$iso_kw <br />\n";
print "US-WOY=$us_woy <br />\n";
Modul Date::Calc
use Date::Calc qw(Week_of_Year);
($kw,$yy) = Week_of_Year($yy,$mo,$dd);
print "ISO-KW=$kw <br />\n";

PHP

Die Funktion strftime() arbeitet genauso wie in Perl (Absatz oben). Sie ist im Modul date enthalten, welches normalerweise in jeder PHP-Distribution enthalten ist.
Details zu PHP-Modulen und zum Modul date

$uts = time();
$iso_kw = strftime("%V",$uts)+0;
$us_woy = strftime("%U",$uts)+0;
print "ISO-KW=$iso_kw <br />\n";
print "US-WOY=$us_woy <br />\n";

VBA

Die Funktion woy_iso() des Beispiels berechnet die ISO-Kalenderwoche und kann auch als 'BenutzerInnen-Spezifische Funktion' für jedes Standard Kalkulations-Programm (LibreOffice, Excel, ...) eingesetzt werden.
Das Argument datum ist ein Datum (mit oder ohne Uhrzeit) im Y1900-Format.
In Variable d wird das Datum isoliert, d.h. von der Uhrzeit befreit.
Das Referenz-Datum des Jahres wird mit Hilfsfunktion dref_iso() berechnet und getestet.
Wenn das gesuchte Datum davor liegt (dif<0), dann wird das Referenz-Datum des Vorjahrs herangezogen.
Wenn das gesuchte Datum am Jahresende liegt, wird geprüft, ob es in KW1 des Folgejahres fällt.
Zuletzt wird die ISO-Woche aus der Differenz dif zum Referenz-Datum berechnet und zurückgegeben.

Die Funktion woy_us() berechnet auf ähnliche Weise die US-Kalenderwoche.
Die Hilfsfunktion dref_us() zur Berechnung des US-Referenz-Datums ist bereits in woy_us() integriert und wird daher zur Berechnung nicht benötigt. Sie wird nur zur Demonstration gezeigt, wenn sie das Referenz-Datum eines Jahres yy selbst berechnen wollen.

Details zum Thema VBA @ Datum & Zeit
Function woy_iso(datum As Double) As Integer
Dim dif, difn As Integer
Dim d As Long
d = Int(datum)
dif = d - dref_iso(Year(datum))
If dif < 0 Then
dif = d - dref_iso(Year(datum) - 1)
ElseIf dif >= 358 Then
difn = d - dref_iso(Year(datum) + 1)
If difn>= 0 Then dif = difn
End If
woy_iso = (dif \ 7) + 1
End Function

Private Function dref_iso(ByVal yy As Integer) As Long
Dim r As Long
r = DateSerial(yy, 1, 4)
dref_iso = r - Weekday(r, vbMonday) + 1
End Function

Function woy_us(datum As Double) As Integer
Dim d, r As Long
d = Int(datum)
r = DateSerial(Year(datum), 1, 1)
r = r - Weekday(r, vbSunday) + 1
woy_us = ((d - r) \ 7) + 1
End Function

Private Function dref_us(ByVal yy As Integer) As Long
Dim r As Long
r = DateSerial(yy, 1, 1)
dref_us = r - Weekday(r, vbSunday) + 1
End Function

XHTML CSS