【问题标题】:MS Access get ISO standard week numberMS Access 获取 ISO 标准周数
【发布时间】:2016-01-12 11:06:52
【问题描述】:

我很惊讶我在网上找不到任何现有的解决方案,但我只需要一个返回 ISO 标准周数的 SQL 函数(即第 1 周的开始总是一年中的第一个星期一)。

没有一个 DatePart 函数选项始终返回正确的结果。我曾想过“vbFirstFourDays - 从新年至少有四天的第一周开始”选项。但今天(1 月 12 日)测试它返回第 3 周,而不是第 2 周(我的表达是 DatePart("ww",Now(),2)

今年 ISO 第 1 周从 1 月 4 日开始,明年 1 月 2 日开始,去年是 1 月 5 日。

非常感谢

【问题讨论】:

  • 试试DatePart("ww",Now(),2,2)。您的示例实际上省略了 firstweekofyear 参数。
  • 哎呀,我真傻,非常感谢,工作正常:)

标签: ms-access iso week-number


【解决方案1】:

DatePart 函数在将vbMonday 用于firstdayofweek 参数并将vbFirstFourDays 用于firstweekofyear 参数,例如,

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

或者,直接在 Access 查询中使用时

DatePart("ww", Date(), 2, 2)

* 请注意,here 记录的错误显然从未得到修复,因此 21st 世纪的下一个星期一报告为在第 53 周,根据到 ISO-8601 他们应该在下一年的第 1 周:

2003-12-29
2007-12-31
2019-12-30
2031-12-29
2035-12-31
2047-12-30
2059-12-29
2063-12-31
2075-12-30
2087-12-29
2091-12-31

【讨论】:

  • 访问是否传播the Oleaut23.dll bug
  • 不幸的是,确实如此。我已经更新了我的答案。谢谢!
【解决方案2】:

继 Gord Thompson 之后,Microsoft 提供了一种解决方法,可在所有情况下返回正确的 ISO 周。它只是将第 53 周更改为第 1 周。只需将其放入 VBA 模块中,然后您就可以在 Excel/Access 中使用该功能。

Public Function ISOWeek(MyDate As Date) As Integer

      ISOWeek = Format(MyDate, "ww", vbMonday, vbFirstFourDays)
      If ISOWeek > 52 Then
         If Format(MyDate + 7, "ww", vbMonday, vbFirstFourDays) = 2 Then ISOWeek = 1
      End If

End Function

【讨论】:

    【解决方案3】:

    除了 DatePart 返回的 2 周数字之外,ISO 周数存在更多问题。

    1 月 1 日的星期五应该在上一年的第 53 周

    12 月 31 日的星期一应该在下一年的第 1 周

    欧洲的许多企业都使用四位数字来同时显示年份和星期。在这些情况下:

    Frid​​ay #01/01/2021# 应显示为“2153”周

    星期一 #12/31/2018# 应显示为“1901”周

    我围绕 DatePart 函数创建了 2 个包装器,以添加正确的年份并显示正确的周数,以防 DatePart 出错。

    Public Function ISO_YYWW(dat As Date) As String ' ISO 8601 / NEN 2772
        Dim ww As Integer
        ww = CInt(ISO_WW(dat))
        If ww >= 52 And Val(Format(dat, "ww")) <= 2 Then
           ISO_YYWW = Format(((Year(dat) - 1) Mod 100), "00") & Format(ww, "00")
        ElseIf ww = 1 And Month(dat) = 12 Then
           ISO_YYWW = Format(((Year(dat) + 1) Mod 100), "00") & Format(ww, "00")
        Else
           ISO_YYWW = Format(dat, "YY") & Format(ww, "00")
        End If
    End Function
    Public Function ISO_WW(dat As Date) As String ' ISO 8601 / NEN 2772
        If Format(dat, "DD-MM") = "31-12" And DatePart("W", dat, vbMonday, vbFirstFourDays) = 1 Then ' 31-dec on a monday
           ISO_WW = "01"
        ElseIf Format(dat, "DD-MM") = "30-12" And DatePart("W", dat, vbMonday, vbFirstFourDays) = 1 Then ' 30-dec on a monday
           ISO_WW = "01"
        ElseIf Format(dat, "DD-MM") = "29-12" And DatePart("W", dat, vbMonday, vbFirstFourDays) = 1 Then ' 29-dec on a monday
           ISO_WW = "01"
        Else
           ISO_WW = Format(DatePart("ww", dat, 2, 2), "00")
        End If
    End Function
    

    我从 1970 年到 2021 年进行了测试,使用此代码没有发现任何问题

    Sub test()
        Dim dat As Date, yy As Integer, f As Integer
        f = FreeFile
        Open CodeDb.Name & ".txt" For Output As #f
        Print #f, "date", "day", "ISO_WW / DOW", "ISO_YYWW"
        For yy = 1970 To 2021
            For dat = CDate("31/12/" & yy) - 7 To CDate("31/12/" & yy) + 7
                If ISO_WW(dat) >= 52 Or ISO_WW(dat) = "53" Or Val(ISO_WW(dat)) = 1 Then
                   Print #f, Format(dat, "yyyy-mm-dd"), Format(dat, "DDD"), ISO_WW(dat) & " / " & DatePart("W", dat, vbMonday, vbFirstFourDays), ISO_YYWW(dat)
                End If
            Next dat
            Print #f, ""
        Next yy
        Close #f
    End Sub
    

    【讨论】:

      猜你喜欢
      • 2018-03-17
      • 1970-01-01
      • 2015-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多