Biçim veya DatePart işlevleri Yılın son Pazartesi günü için yanlış hafta numarasını döndürebilir

Not

Office 365 ProPlus, Microsoft 365 Kurumsal Uygulamaları olarak yeniden adlandırılıyor. Bu değişiklik hakkında daha fazla bilgi için, bu blog yazısını okuyun.

Uyarı

Bu işlevin kullanımı ile ilgili bir sorun vardır. Bazı takvim yıllarında son Pazartesi, 1. Daha fazla bilgi ve geçici çözüm için Bkz. Biçim veya DatePart işlevleri Yılın son Pazartesi günü için yanlış hafta numarasını döndürebilir.

Belirtiler

Aşağıdaki sözdizimini kullanarak tarihlerin hafta numarasını belirlemek için Biçim veya DatePart işlevini kullandığınızda:

Biçim(AnyDate, "ww", vbMonday, vbFirstFourDays)

DatePart("ww", AnyDate, vbMonday, vbFirstFourDays)

bazı takvim yıllarında son Pazartesi hafta 1 olması gereken 53 hafta olarak döndürülür.

Neden

ISO 8601 standardına göre bir tarihin hafta numarası belirlenirken, oleaut32.dll dosyasına temel işlev çağrısı, belirli yıllardaki son Pazartesi günü için 1.

Çözüm

ISO 8601 standardının kurallarına göre Hafta numarasını döndürmek için kullanıcı tanımlı bir işlev kullanın. Bu makalede bir örnek yer alabilmiştir.

Daha Fazla Bilgi

ISO 8601 standardı Avrupa'da yaygın olarak kullanılmaktadır ve aşağıdakileri içerir:

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."

Bu, Takvim haftaları için bu kurallar uygulanarak uygulanabilir:

  • Bir yıl 52 veya 53 takvim haftasına bölünür.
  • Bir takvim haftasının 7 günü vardır. Pazartesi birinci, Pazar 7.
  • Yılın ilk takvim haftası en az 4 gün içeren olandır.
  • Bir yıl Pazar günü sonuçlandırılamazsa, 1-3 son günü gelecek yılın ilk takvim haftasına veya gelecek yılın ilk 1-3 günü bugünün son takvim haftasına aittir.
  • Bir Perşembe günü başlayan veya sonuçlanan sadece bir yıl 53 takvim haftası vardır.

Visual Basic for Applications'da DateSerial işlevi dışındaki tüm tarih işlevleri Oleaut32.dll dosyasına yapılan çağrılardan gelir. Biçim() ve DatePart() işlevleri belirli bir tarihin takvim hafta numarasını döndürebildiği için, her ikisi de bu hatadan etkilenir. Bu sorunu önlemek için, bu makalenin sağladığı alternatif kodu kullanmanız gerekir.

Davranışı Çoğaltma Adımları

  1. Office uygulaması (Alt + F11) içinde Visual Basic projesini açın.

  2. Proje menüsünden yeni bir modül ekleyin.

  3. Aşağıdaki kodu modüle yapıştırın:

    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
    
  4. Zaten açık değilse Hemen Pencereyi açmak için (Ctrl + G) kullanın.

  5. Tip **mi? **Hemen penceresinde Test1 ve Enter tuşuna basın, Hemen penceresinde aşağıdaki sonuçlara dikkat edin:

    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
    

    Bu biçimle, tüm haftalar Pazartesi ile başlar, böylece 12/29/2003 Hafta 1 başlangıcı ve Hafta 53 parçası olarak kabul edilmelidir unutmayın.

  6. Tip **mi? **Hemen penceresinde Test2 ve bu sorunla karşılaşan belirtilen aralıktaki tarihlerin listesini görmek için Enter tuşuna basın. Liste, Biçime göre döndürülen tarih, Hafta günü (her zaman Pazartesi), Biçime göre döndürülen Hafta # (53) ve dönmesi gereken Hafta numarasını (1) içerir. Örneğin:

    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
    ...
    

Geçi -ci çözüm

Biçim veya DatePart işlevlerini kullanıyorsanız, iade değerini denetlemeniz gerekir. 53 olduğunda, başka bir çek çalıştırın ve gerekirse 1'in iadesini zorleyin. Bu kod örneği bunu yapmanın bir yolunu gösterir:

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

Yukarıda açıklanan ISO 8601 kurallarını uygulayan kod yazarak Hafta numarasını belirlemek için bu işlevleri kullanmaktan kaçınabilirsiniz. Aşağıdaki örnek, Hafta numarasını döndürmek için bir değiştirme işlevi gösterir.

Adım Adım Örnek

  1. Office uygulaması (Alt + F11) içinde Visual Basic projesini açın.

  2. Proje menüsünden yeni bir modül ekleyin.

  3. Aşağıdaki kodu modüle yapıştırın:

    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
    
  4. Zaten açık değilse Hemen Pencereyi açmak için (Ctrl + G) kullanın.

  5. Tip **mi? **Hemen penceresinde Test3 ve Enter tuşuna basın, Hemen penceresinde aşağıdaki sonuçlara dikkat edin:

    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
    

    Pazartesi olması gerektiği gibi Hafta 1 olarak kabul edilir unutmayın.