Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Warnung
Es gibt ein Problem mit der Verwendung dieser Funktion. Der letzte Montag in einigen Kalenderjahren kann als Woche 53 zurückgegeben werden, wenn es Woche 1 sein soll. Weitere Informationen und eine Problemumgehung finden Sie unter "Format" oder "DatePart"-Funktionen, die die falsche Wochennummer für den letzten Montag im Jahr zurückgeben können.
Symptome
Wenn Sie entweder die Funktion "Format" oder "DatePart" verwenden, um die Wochenzahl für Datumsangaben mithilfe der folgenden Syntax zu bestimmen:
Format(AnyDate, "ww", vbMonday, vbFirstFourDays)
DatePart("ww", AnyDate, vbMonday, vbFirstFourDays)
Der letzte Montag in einigen Kalenderjahren wird als Woche 53 zurückgegeben, wenn es Woche 1 sein soll.
Ursache
Beim Bestimmen der Wochennummer eines Datums gemäß dem ISO 8601-Standard gibt der zugrunde liegende Funktionsaufruf für die Oleaut32.dll Datei versehentlich Woche 53 statt Woche 1 für den letzten Montag in bestimmten Jahren zurück.
Beschluss
Verwenden Sie eine benutzerdefinierte Funktion, um die Wochennummer basierend auf den Regeln für den ISO 8601-Standard zurückzugeben. Ein Beispiel ist in diesem Artikel enthalten.
Mehr Informationen
Der ISO 8601-Standard wird in Europa umfassend eingesetzt und umfasst:
ISO 8601 "Data elements and interchange formats - Information interchange - Representation of dates and times"
ISO 8601 : 1988 (E) paragraph 3.17:
"week, calendar: A seven day period within a calendar year, starting on a Monday and identified by its ordinal number within the year; the first calendar week of the year is the one that includes the first Thursday of that year. In the Gregorian calendar, this is equivalent to the week which includes 4 January."
Sie kann durch Anwenden dieser Regeln für Kalenderwochen implementiert werden:
- Ein Jahr ist in 52 oder 53 Kalenderwochen unterteilt.
- Eine Kalenderwoche hat sieben Tage. Montag ist Tag 1 und Sonntag ist Tag 7.
- Die erste Kalenderwoche eines Jahres ist die Kalenderwoche, die mindestens vier Tage enthält.
- Wenn ein Jahr nicht am Sonntag abgeschlossen ist, gehören entweder die 1-3 letzten Tage zur ersten Kalenderwoche des nächsten Jahres, oder die ersten 1-3 Tage des nächsten Jahres gehören zur letzten Kalenderwoche des aktuellen Jahres.
- Nur ein Jahr, das am Donnerstag beginnt oder endet, hat 53 Kalenderwochen.
In Visual Basic und Visual Basic für Applikationen stammen alle Datumsfunktionen, mit Ausnahme der DateSerial-Funktion, aus Aufrufen der Oleaut32.dll Datei. Da sowohl die Funktionen "Format()" als auch "DatePart()" die Kalenderwochennummer für ein bestimmtes Datum zurückgeben können, sind beide von diesem Fehler betroffen. Um dieses Problem zu vermeiden, müssen Sie den alternativen Code verwenden, den dieser Artikel bereitstellt.
Schritte zum Reproduzieren des Verhaltens
Öffnen Sie das Visual Basic-Projekt in einer Office-Anwendung (ALT+ F11).
Fügen Sie im Menü "Projekt " ein neues Modul hinzu.
Fügen Sie den folgenden Code in das Modul ein:
Option Explicit Public Function Test1() ' This code tests a "problem" date and the days around it Dim DateValue As Date Dim i As Integer Debug.Print " Format function:" DateValue = #12/27/2003# For i = 1 To 4 ' examine the last 4 days of the year DateValue = DateAdd("d", 1, DateValue) Debug.Print "Date: " & DateValue & " Day: " & _ Format(DateValue, "ddd") & " Week: " & _ Format(DateValue, "ww", vbMonday, vbFirstFourDays) Next i End Function Public Function Test2() ' This code lists all "Problem" dates within a specified range Dim MyDate As Date Dim Years As Long Dim days As Long Dim woy1 As Long Dim woy2 As Long Dim ToPrint As String For Years = 1850 To 2050 For days = 0 To 3 MyDate = DateSerial(Years, 12, 28 + days) woy1 = Format(MyDate, "ww", vbMonday, vbFirstFourDays) woy2 = Format(MyDate, "ww", vbMonday, vbFirstFourDays) If woy2 > 52 Then If Format(MyDate + 7, "ww", vbMonday, vbFirstFourDays) = 2 Then _ woy2 = 1 End If If woy1 <> woy2 Then ToPrint = MyDate & String(13 - Len(CStr(MyDate)), " ") ToPrint = ToPrint & Format(MyDate, "dddd") & _ String(10 - Len(Format(MyDate, "dddd")), " ") ToPrint = ToPrint & woy1 & String(5 - Len(CStr(woy1)), " ") ToPrint = ToPrint & woy2 Debug.Print ToPrint End If Next days Next Years End Function
Verwenden Sie (STRG+G), um das Direktfenster zu öffnen, wenn es noch nicht geöffnet ist.
Geben Sie ?Test1 im Direktfenster ein und drücken Sie die EINGABETASTE, und beachten Sie die folgenden Ergebnisse im Direktfenster:
Format function: Date: 12/28/03 Day: Sun Week: 52 Date: 12/29/03 Day: Mon Week: 53 Date: 12/30/03 Day: Tue Week: 1 Date: 12/31/03 Day: Wed Week: 1
Mit diesem Format beginnen alle Wochen mit Montag, damit der 29. Dezember 2003 als Beginn der Woche 1 und nicht teil der Woche 53 betrachtet werden sollte.
Geben Sie ?Test2 im Direktfenster ein, und drücken Sie die EINGABETASTE, um eine Liste der Datumsangaben im angegebenen Bereich anzuzeigen, die von diesem Problem betroffen sind. Die Liste enthält das Datum, den Wochentag (immer Montag), die von Format (53) zurückgegebene Woche # und die Zahl der Woche, die zurückgegeben werden soll (1.) Zum Beispiel:
12/29/1851 Monday 53 1 12/31/1855 Monday 53 1 12/30/1867 Monday 53 1 12/29/1879 Monday 53 1 12/31/1883 Monday 53 1 12/30/1895 Monday 53 1 ...
Problemumgehungen
Wenn Sie die Funktionen "Format" oder "DatePart" verwenden, müssen Sie den Rückgabewert überprüfen. Wenn der Wert 53 erreicht, führen Sie eine weitere Prüfung aus und erzwingen Sie bei Bedarf eine Rückgabe von 1. Dieses Codebeispiel veranschaulicht eine Möglichkeit, dies zu tun:
Function WOY (MyDate As Date) As Integer ' Week Of Year
WOY = Format(MyDate, "ww", vbMonday, vbFirstFourDays)
If WOY > 52 Then
If Format(MyDate + 7, "ww", vbMonday, vbFirstFourDays) = 2 Then WOY = 1
End If
End Function
Sie können diese Funktionen vermeiden, um die Wochennummer zu bestimmen, indem Sie Code schreiben, der die oben beschriebenen ISO 8601-Regeln implementiert. Im folgenden Beispiel wird eine Ersetzungsfunktion veranschaulicht, um die Wochennummer zurückzugeben.
Schritt-für-Schritt-Beispiel
Öffnen Sie das Visual Basic-Projekt in einer Office-Anwendung (ALT+ F11).
Fügen Sie im Menü "Projekt " ein neues Modul hinzu.
Fügen Sie den folgenden Code in das Modul ein:
Option Explicit Function WeekNumber(InDate As Date) As Integer Dim DayNo As Integer Dim StartDays As Integer Dim StopDays As Integer Dim StartDay As Integer Dim StopDay As Integer Dim VNumber As Integer Dim ThurFlag As Boolean DayNo = Days(InDate) StartDay = Weekday(DateSerial(Year(InDate), 1, 1)) - 1 StopDay = Weekday(DateSerial(Year(InDate), 12, 31)) - 1 ' Number of days belonging to first calendar week StartDays = 7 - (StartDay - 1) ' Number of days belonging to last calendar week StopDays = 7 - (StopDay - 1) ' Test to see if the year will have 53 weeks or not If StartDay = 4 Or StopDay = 4 Then ThurFlag = True Else ThurFlag = False VNumber = (DayNo - StartDays - 4) / 7 ' If first week has 4 or more days, it will be calendar week 1 ' If first week has less than 4 days, it will belong to last year's ' last calendar week If StartDays >= 4 Then WeekNumber = Fix(VNumber) + 2 Else WeekNumber = Fix(VNumber) + 1 End If ' Handle years whose last days will belong to coming year's first ' calendar week If WeekNumber > 52 And ThurFlag = False Then WeekNumber = 1 ' Handle years whose first days will belong to the last year's ' last calendar week If WeekNumber = 0 Then WeekNumber = WeekNumber(DateSerial(Year(InDate) - 1, 12, 31)) End If End Function Function Days(DayNo As Date) As Integer Days = DayNo - DateSerial(Year(DayNo), 1, 0) End Function Public Function Test3() Dim DateValue As Date, i As Integer Debug.Print " WeekNumber function:" DateValue = #12/27/2003# For i = 1 To 4 ' examine the last 4 days of the year DateValue = DateAdd("d", 1, DateValue) Debug.Print "Date: " & DateValue & " Day: " & _ Format(DateValue, "ddd") & " Week: " & WeekNumber(DateValue) Next i End Function
Verwenden Sie (STRG+G), um das Direktfenster zu öffnen, wenn es noch nicht geöffnet ist.
Geben Sie im Direktfenster ?Test3 ein und drücken Sie die EINGABETASTE, beachten Sie die folgenden Ergebnisse:
WeekNumber function: Date: 12/28/03 Day: Sun Week: 52 Date: 12/29/03 Day: Mon Week: 1 Date: 12/30/03 Day: Tue Week: 1 Date: 12/31/03 Day: Wed Week: 1
Montag gilt als Woche 1, wie es sein sollte.