BUG: Формат или функции DatePart может вернуть неправильный номер недели последний понедельник в год

Переводы статьи Переводы статьи
Код статьи: 200299 - Vizualiza?i produsele pentru care se aplic? acest articol.
Развернуть все | Свернуть все

В этой статье

Проблема

При использовании любойФормат:-или-Функции DatePartфункции для определения номера недели для даты, используя следующий синтаксис:
Format(AnyDate, "ww", vbMonday, vbFirstFourDays)

DatePart("ww", AnyDate, vbMonday, vbFirstFourDays)
				
последний понедельник в некоторых календарного года возвращаются в виде Неделя 53, когда он должен быть 1 неделя.

Причина

При определении количества недель дату в соответствии с ISO 8601 стандартных, базовые функции файл Oleaut32.dll ошибочно возвращает Неделя 53 вместо неделя 1 последний понедельник в определенные годы.

Решение

Использование определяемой пользователем функции для возвращения числа неделя, в соответствии с правилами стандарта ISO 8601. Пример включен в этой статье.

Статус

Корпорация Майкрософт подтверждает, что это является проблемой в файл Oleaut32.dll.

Дополнительная информация

Стандарт ISO 8601 широко используется в Европе и включает в себя следующее:
  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."
				
Это может быть реализовано путем применения этих правил для недели календаря:
  • Год делится на 52 или 53 календарных недель.
  • Неделя в календаре имеет 7 дней. Понедельник — день 1, воскресенье — 7 дней.
  • Первой недели года календаря является, содержащий хотя бы на 4 дня.
  • Если год не является памятью на воскресенье, принадлежат его последнего дня 1-3 для следующего года первая неделя календаря или первые дни 1-3 следующего года принадлежит последняя неделя в календаре текущего года.
  • Только начальную или concluding на четверг году 53 календарных недель.
В Visual Basic и Visual Basic для приложений, все даты за исключением функций,DateSerialфункции, поступают из вызовов файла Oleaut32.dll. Так как обаFormat()иDatePart()функции могут возвращать номер недели в календаре для определенной даты, оба подвержены этой ошибки. Чтобы избежать этого, необходимо использовать другой код, эта статья содержит.

Действия для воспроизведения поведения:

  1. Запустите стандартный EXE-файла проекта в Visual Basic. По умолчанию будет создана форма Form1..
  2. Добавить дваCommandButtonsв форму Form1.
  3. Вставьте следующий код в окно кода Form1:
    Option Explicit
    
    Private Sub Command1_Click()
    ' 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 Sub
    
    Private Sub Command2_Click()
    ' 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 Sub
    					
  4. Удерживая клавишу CTRL и нажмите клавишу G, чтобы открыть окно "Интерпретация".
  5. Запустите проект, выберите командуCommand1и обратите внимание на следующие результаты в окне интерпретации.
       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
    						
    Обратите внимание, что все недель данного формата начинаются с понедельника, таким образом, чтобы 12/29/2003 должны быть рассмотрены 1 неделя и не является частью Неделя 53.
  6. Нажмите на кнопкуCommand2Чтобы просмотреть список дат в указанном диапазоне, эта проблема. Список содержит дату, день недели (всегда понедельник) недели # формат (53) и она должна возвращать число недель (1). Например,:
    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
    ...
    					

Устранение проблем

При использованииФормат:-или-Функции DatePartфункции, необходимо проверить возвращаемое значение и, когда 53, проверка другой и принудительного возврата 1, если это необходимо. Этот пример кода демонстрирует один из способов сделать это:
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
				
Можно избежать с помощью этих функций для определения номера недель путем написания кода, который реализует правила ISO 8601, описанные выше. В следующем примере демонстрируется замена функция, возвращающая номер недели.

Пример выполнения шага

  1. Запустите стандартный EXE-файла проекта в Visual Basic. По умолчанию будет создана форма Form1..
  2. ИзProjectменю Добавить новый модуль, а затем вставьте в следующем коде:
    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
    					
  3. ДобавитьCommandButtonв форму Form1.
  4. Вставьте следующий код в окно кода Form1:
    Private Sub Command1_Click()
       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 Sub
    					
  5. Удерживая клавишу CTRL и нажмите клавишу G, чтобы открыть окно "Интерпретация".
  6. Запустите проект и выберите командуCommand1для просмотра в окно проверки следующие результаты:
       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
    					
    Обратите внимание, что понедельник считается равным 1 неделя, как оно должно быть.

Свойства

Код статьи: 200299 - Последний отзыв: 16 ноября 2010 г. - Revision: 2.0
Информация в данной статье относится к следующим продуктам.
  • Microsoft Visual Basic 6.0 Professional Edition
  • Microsoft Visual Basic Control Creation Edition
  • Microsoft Visual Basic 5.0 Learning Edition
  • Microsoft Visual Basic 5.0 Professional Edition
  • Microsoft Visual Basic 5.0 Enterprise Edition
  • Microsoft Visual Basic 4.0 Standard Edition
  • Microsoft Visual Basic for Applications 6.0
Ключевые слова: 
kbbug kbdatetime kbpending kbmt KB200299 KbMtru
Переведено с помощью машинного перевода
ВНИМАНИЕ! Перевод данной статьи был выполнен не человеком, а с помощью программы машинного перевода, разработанной корпорацией Майкрософт. Корпорация Майкрософт предлагает вам статьи, переведенные как людьми, так и средствами машинного перевода, чтобы у вас была возможность ознакомиться со статьями базы знаний KB на родном языке. Однако машинный перевод не всегда идеален. Он может содержать смысловые, синтаксические и грамматические ошибки, подобно тому как иностранец делает ошибки, пытаясь говорить на вашем языке. Корпорация Майкрософт не несет ответственности за неточности, ошибки и возможный ущерб, причиненный в результате неправильного перевода или его использования. Корпорация Майкрософт также часто обновляет средства машинного перевода.
Эта статья на английском языке:200299

Отправить отзыв

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com