错误: 格式或 DatePart 函数可以返回错误的周数年中的最后一个星期一

文章翻译 文章翻译
文章编号: 200299 - 查看本文应用于的产品
展开全部 | 关闭全部

本文内容

症状

当您使用 格式DatePart 函数使用以下语法的日期确定周编号:
Format(AnyDate, "ww", vbMonday, vbFirstFourDays)

DatePart("ww", AnyDate, vbMonday, vbFirstFourDays)
				
周 53 时它应该是第 1 周的形式返回某些日历年中上月。

原因

在确定了 ISO 8601 标准对应的日期的星期数时 Oleaut32.dll 文件基础的函数调用错误地返回特定年中周 53 而不是第 1 周的最后一个星期一。

解决方案

使用用户定义函数返回的 ISO 8601 标准规则基于的周数。在这篇文章中包含一个示例。

状态

Microsoft 已经确认这是 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."
				
这可以通过日历周应用这些规则来实现:
  • 一年分为 53 或 52 日历周。
  • 日历周有 7 天。星期一是第一天,星期日是 7 天。
  • 一年的第一个日历周是包含在至少 4 个工作日。
  • 如果一年不一个星期日结束,其 1-3 天属于下一年的第一个日历周,或下一年中的第一个 1-3 天属于存在年的最后一个日历周。
  • 仅一年开始或结束是星期四有 53 日历周。
在 Visual Basic 和 Visual Basic 应用程序的除外 DateSerial 功能的所有日期功能都来自 Oleaut32.dll 文件的调用。因为 format ()DatePart() 函数可以返回给定日期的日历周编号,同时会影响此 bug。若要不必此问题,您必须使用这篇文章介绍了在其他代码。

重现行为的步骤

  1. 启动 Visual Basic 中的标准 EXE 项目。默认情况下创建 Form1。
  2. 向 Form1 中添加两个 CommandButtons
  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
    						
    注意这种格式与所有的周开始与星期一,以便开始的第 1 周和不是周 53 的一部分,应考虑 12/29/2003年。
  6. 单击上 Command2 若要查看的指定区域中遇到此问题的日期列表。该列表包含日期、 周的天 (始终星期一) Week # 所返回的格式 (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. 启动 Visual Basic 中的标准 EXE 项目。默认情况下创建 Form1。
  2. 项目 菜单中添加一个新的模块,然后粘贴下面的代码:
    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. 向 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 - 最后修改: 2004年6月24日 - 修订: 3.0
这篇文章中的信息适用于:
  • Microsoft Visual Basic 6.0 学习版
  • Microsoft Visual Basic 6.0 专业版
  • Microsoft Visual Basic Enterprise Edition for Windows 6.0
  • Microsoft Visual Basic Control Creation Edition
  • Microsoft Visual Basic 5.0 学习版
  • Microsoft Visual Basic 5.0 专业版
  • Microsoft Visual Basic 5.0 企业版
  • Microsoft Visual Basic 4.0 标准版
  • Microsoft Visual Basic 4.0 专业版
  • Microsoft Visual Basic 4.0 32-Bit Enterprise Edition
  • Microsoft Visual Basic for Applications 5.0
  • Microsoft Visual Basic for Applications 6.0
关键字:?
kbmt kbbug kbdatetime kbpending KB200299 KbMtzh
机器翻译
注意:这篇文章是由无人工介入的微软自动的机器翻译软件翻译完成。微软很高兴能同时提供给您由人工翻译的和由机器翻译的文章, 以使您能使用您的语言访问所有的知识库文章。然而由机器翻译的文章并不总是完美的。它可能存在词汇,语法或文法的问题,就像是一个外国人在说中文时总是可能犯这样的错误。虽然我们经常升级机器翻译软件以提高翻译质量,但是我们不保证机器翻译的正确度,也不对由于内容的误译或者客户对它的错误使用所引起的任何直接的, 或间接的可能的问题负责。
点击这里察看该文章的英文版: 200299
Microsoft和/或其各供应商对于为任何目的而在本服务器上发布的文件及有关图形所含信息的适用性,不作任何声明。 所有该等文件及有关图形均"依样"提供,而不带任何性质的保证。Microsoft和/或其各供应商特此声明,对所有与该等信息有关的保证和条件不负任何责任,该等保证和条件包括关于适销性、符合特定用途、所有权和非侵权的所有默示保证和条件。在任何情况下,在由于使用或运行本服务器上的信息所引起的或与该等使用或运行有关的诉讼中,Microsoft和/或其各供应商就因丧失使用、数据或利润所导致的任何特别的、间接的、衍生性的损害或任何因使用而丧失所导致的之损害、数据或利润不负任何责任。

提供反馈

 

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