Last Update: 2024 - 05 - 21 |
VBA - Kalenderwoche und Jahr aus einem Datum ermittelnvon Philipp Stiefel, ursprünglich veröffentlicht 01. Juni 2016 Du willst in Access/VBA die Kalenderwoche eines Datums ermitteln. – Eigentlich nichts leichter als das. Die Format-Funktion liefert genau diese als Ergebnis, wenn man als das gewünschte Format „ww“ angibt. Nun ist die Kalenderwoche für sich genommen nicht aussagefähig genug, wenn man Zeiträume betrachtet, die über die Grenzen eines Jahres hinausgehen. Daher macht es oft Sinn, zusätzlich zu der Woche auch noch das Jahr anzuzeigen. Auch das ist sollte nicht schwer sein, gibt es doch die Year-Funktion, um ganz einfach das Jahr eines Datums zu ermitteln. Noch einfacher ist es, sowohl die Kalenderwoche als auch das Jahr von der Format-Funktion ermitteln zu lassen. Dazu kannst du den Formatausdruck „ww-yyyy“ verwenden. Der Funktionsaufruf dafür im Direktfenster sieht aus wie folgt:
? Format(cdate("2016-06-15"),"ww-yyyy",vbUseSystemDayOfWeek,vbUseSystem)
24-2016
Alles gut? Nein, leider nicht. Wenn es das wäre, hätte ich diesen Artikel nicht geschrieben. Problematisch wird es direkt um den Jahreswechsel herum. Also probieren wir den obigen Ausdruck mal für den 01.01.2016 aus.
? Format(cdate("2016-01-01"),"ww-yyyy",vbUseSystemDayOfWeek,vbUseSystem)
53-2016
Es ist in der Tat die KW 53; soweit ok. Aber es ist nicht die KW 53 des Jahres 2016, sondern die KW 53 des Jahres 2015! Die Format-Funktion hat hier eine Schwäche. Sie liefert immer die Jahreszahl des Datums. Für alle anderen Formate ist das auch korrekt, nicht aber in Zusammenhang mit der Kalenderwoche. In der geltenden Norm ISO 8601 für Datumsformate und Zeitangaben ist definiert, dass die erste Woche des Jahres diejenige ist, die den ersten Donnerstag im Januar enthält. D.h. die Kalenderwoche 53 des Jahres 2015 geht bis einschließlich 03.01.2016. Beim vorigen Jahreswechsel ist es genau andersherum. Am 29.12.2014 beginnt bereits die KW 1 des Jahres 2015. Die Access/VBA-Format-Funktion kann das nicht berücksichtigen, da sie immer das jeweilige Jahr des Datums ausgibt, und nicht auf die besondere Situation bei der Kalenderwoche reagieren kann. Um dieses Problem zu lösen, habe ich eine erweiterte Funktion geschrieben, die nach der Ermittlung des Jahres noch auf die beiden oben genannten Fälle prüft.
Das Ergebnis ist die Funktion IsoWeekAndYear:
Function IsoWeekAndYear(ByVal weekDate As Date, Optional ByVal separator As String = "-") As String
Dim week As Integer
Dim weekYear As Integer
week = IsoWeek(weekDate)
weekYear = Year(weekDate)
If week >= 52 And Month(weekDate) = 1 Then
weekYear = weekYear - 1
ElseIf week = 1 And Month(weekDate) = 12 Then
weekYear = weekYear + 1
End If
IsoWeekAndYear = week & separator & weekYear
End Function
Public Function IsoWeek(ByVal weekDate As Date) As Integer ' Workaround for Wrong Week Number for last Monday in Year - based on https://support.microsoft.com/en-us/kb/200299 Dim retVal As Integer retVal = Format(weekDate, "ww", vbMonday, vbFirstFourDays) If retVal > 52 Then If Format(DateAdd("d", 7, weekDate), "ww", vbMonday, vbFirstFourDays) = 2 Then retVal = 1 End If End If IsoWeek = retVal End Function Jetzt kannst du die beiden genannten Problemfälle durch die Eingabe im Direktfenster überprüfen:
? IsoWeekAndYear(cdate("2014-12-29"))
1-2015
? IsoWeekAndYear(cdate("2016-01-02"))
53-2015
So soll es sein. :-) Wie du siehst, ermittle ich das Datum nicht direkt mit der Format-Funktion, sondern habe dazu die Funktion IsoWeek geschrieben, die zusätzlich einen uralten, aber immer noch bestehenden, Bug behandelt, der die Format-Funktion u.U. die falsche Woche für den letzten Montag im Jahr zurückgeben lässt. Wenn du dir die beiden oben dargestellten Funktionen in deiner Anwendung kopierst und diese zukünftig für die Ermittlung der Kalenderwoche verwendest, sollten die Probleme mit der Ermittlung der Kalenderwoche damit gelöst sein.
Ich werde Deine Email-Addresse niemals weitergeben. Du kannst den Newsletter jederzeit abbestellen. © 1999 - 2024 by Philipp Stiefel - Datenschutzerklärung |