MS Access 获取 ISO 标准周数
MS Access get ISO standard week number
我很惊讶我在网上找不到任何现有的解决方案,但我只需要一个 SQL 函数,它 return 是 ISO 标准周数(即一周的开始1 始终是一年中的第一个星期一)。
None 的 DatePart 函数选项始终 return 正确的结果。我曾考虑过 "vbFirstFourDays - Start with the first week that has at least four days in the new year." 选项,但在今天(1 月 12 日)return 的第 3 周而不是第 2 周对其进行了测试(我的表达方式是 DatePart("ww",Now(),2)
)
今年 ISO 第 1 周从 1 月 4 日开始,明年是 1 月 2 日,去年是 1 月 5 日。
非常感谢
当firstdayofweek 使用vbMonday
时,DatePart 函数确实几乎* 正确计算了ISO-8601 周数 参数和 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
继 Gord Thompson 之后,Microsoft 提供了一种解决方法,可以在所有情况下 returns 正确的 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
ISO 周数比 DatePart 返回的 2 周数字存在更多问题。
1 月 1 日的某个星期五应该是上一年的第 53 周
12 月 31 日的星期一应该是下一年的第 1 周
欧洲的许多企业使用四位数字同时显示年份和星期。在这些情况下:
星期五 #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
我很惊讶我在网上找不到任何现有的解决方案,但我只需要一个 SQL 函数,它 return 是 ISO 标准周数(即一周的开始1 始终是一年中的第一个星期一)。
None 的 DatePart 函数选项始终 return 正确的结果。我曾考虑过 "vbFirstFourDays - Start with the first week that has at least four days in the new year." 选项,但在今天(1 月 12 日)return 的第 3 周而不是第 2 周对其进行了测试(我的表达方式是 DatePart("ww",Now(),2)
)
今年 ISO 第 1 周从 1 月 4 日开始,明年是 1 月 2 日,去年是 1 月 5 日。
非常感谢
当firstdayofweek 使用vbMonday
时,DatePart 函数确实几乎* 正确计算了ISO-8601 周数 参数和 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
继 Gord Thompson 之后,Microsoft 提供了一种解决方法,可以在所有情况下 returns 正确的 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
ISO 周数比 DatePart 返回的 2 周数字存在更多问题。
1 月 1 日的某个星期五应该是上一年的第 53 周
12 月 31 日的星期一应该是下一年的第 1 周
欧洲的许多企业使用四位数字同时显示年份和星期。在这些情况下:
星期五 #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