gpt4 book ai didi

.net - 使用 DatePart() 的 ISO8601 周数不正确

转载 作者:行者123 更新时间:2023-12-01 22:43:32 24 4
gpt4 key购买 nike

我的类(class)中有以下 Sub。我没有错误,但结果不符合 ISO-8601 标准

Private Sub calculateAllProperties(ByVal dt As Date)

Select Case dt.DayOfWeek

Case DayOfWeek.Monday

m_CurrentWeekStartDate = dt

Case DayOfWeek.Tuesday

m_CurrentWeekStartDate = DateAdd(DateInterval.Day, -1, dt)

Case DayOfWeek.Wednesday

m_CurrentWeekStartDate = DateAdd(DateInterval.Day, -2, dt)

Case DayOfWeek.Thursday

m_CurrentWeekStartDate = DateAdd(DateInterval.Day, -3, dt)

Case DayOfWeek.Friday

m_CurrentWeekStartDate = DateAdd(DateInterval.Day, -4, dt)

Case DayOfWeek.Saturday

m_CurrentWeekStartDate = DateAdd(DateInterval.Day, -5, dt)

Case DayOfWeek.Sunday

m_CurrentWeekStartDate = DateAdd(DateInterval.Day, -6, dt)

End Select

'Now we have our start point of m_CurrentWeekStartDate we can calculate all other properties.

m_CurrentWeekStartYear = DatePart(DateInterval.Year, m_CurrentWeekStartDate)

m_CurrentWeekNo = DatePart(DateInterval.WeekOfYear, m_CurrentWeekStartDate, Microsoft.VisualBasic.FirstDayOfWeek.Monday, FirstWeekOfYear.FirstFourDays)

m_CurrentWeekNoYear = CurrentWeekNo.ToString("D2") & "-" & CurrentWeekStartYear.ToString
m_CurrentYearWeekNo = CurrentWeekStartYear.ToString & "-" & CurrentWeekNo.ToString("D2")


m_PreviousWeekStartDate = DateAdd(DateInterval.Day, -7, m_CurrentWeekStartDate)

m_PreviousWeekStartYear = DatePart(DateInterval.Year, m_PreviousWeekStartDate)

m_PreviousWeekNo = DatePart(DateInterval.WeekOfYear, m_PreviousWeekStartDate, Microsoft.VisualBasic.FirstDayOfWeek.Monday, FirstWeekOfYear.FirstFourDays)

m_PreviousWeekNoYear = PreviousWeekNo.ToString("D2") & "-" & PreviousWeekStartYear.ToString
m_PreviousYearWeekNo = PreviousWeekStartYear.ToString & "-" & PreviousWeekNo.ToString("D2")

End Sub

给定日期 dt 从 m_CurrentWeekNoYear 返回的值的一些示例

  • 2015 年 7 月 20 日 -> 2015 年 30 日正确
  • 2015 年 9 月 3 日 -> 2015 年 11 月正确
  • 2014 年 12 月 29 日 -> 53-2014 不正确应为 01-2015...使用 02/01/2015还给出了53-2014
  • 05/01/2015 -> 01-2015 不正确应该是 02-2015...使用 09/01/2015 也给出 01-2015
  • 30/12/2013 -> 53-2013 不正确应该是 01-2014...使用 04/01/2014 也给出 53-2013
  • 2014 年 6 月 1 日 -> 2014 年 2 月正确

然后,当我达到实​​际有 53 周的一年时,它就起作用了。

  • 2009 年 12 月 28 日 -> 53-2009 正确
  • 2010 年 4 月 1 日 -> 2010 年 1 月正确

我哪里出了问题,有什么想法吗?

最佳答案

众所周知,使用 DateAdd 和 DatePart 在处理这类事情时很糟糕,但问题是 .NET 计算周数的方式存在(错误)不一致。

请参阅此页面了解更多信息 ISO 8601 Week of Year format in Microsoft .Net

“具体来说,ISO 8601 总是有 7 天的周。如果一年的第一个部分周不包含星期四,则将其算作上一年的最后一周。同样,如果一年的最后一周上一年不包含星期四,则将其[原文如此]视为下一年的第一周。GetWeekOfYear() 有第一个行为,但没有第二个行为”

这是我编写的一些代码,用于根据定义获取 ISO 8601 周数:

“根据 ISO-8601 标准的周数,从星期一开始的周。一年中的第一周是包含该年第一个星期四的周(=“第一个 4 天周”)。最高一年中的周数为 52 或 53。”

''' <summary>
''' Finds the ISO 8601 Week Number based on a given date
''' </summary>
''' <param name="dateValue"></param>
''' <returns></returns>
''' <remarks>ISO 8601 Specifies Monday as the First Day of the week and week one defined as the First Four Day Week</remarks>
Public Shared Function GetIso8601WeekOfYear(ByVal dateValue As DateTime) As Integer
Return GetWeekOfYear(dateValue, DayOfWeek.Sunday, CalendarWeekRule.FirstFourDayWeek)
End Function

它使用以下更通用的方法来根据 ISO 标准的具体情况查找一年中的第几周:

'Need a calendar - Culture's irrelevent since we specify start day of week
Private Shared cal As Calendar = CultureInfo.InvariantCulture.Calendar


''' <summary>
''' Returns the week number of the year based on the Last Day of the Week and the Week One Rule
''' </summary>
''' <param name="dateValue">The date to find the week number for</param>
''' <param name="lastDayOfWeek">The last day of the week</param>
''' <param name="rule">The Definition of Week One</param>
''' <returns>An integer specifying the week number in the year</returns>
''' <remarks></remarks>
Public Shared Function GetWeekOfYear(ByVal dateValue As DateTime, ByVal lastDayOfWeek As DayOfWeek, ByVal rule As CalendarWeekRule) As Integer
'There is a bug in the .NET framework where some dates at the end of the year return the incorrect week number so to find the correct value we need to cheat.
'Find the DayOfWeek that represents the first day based on the last day
Dim firstDayOfWeek As DayOfWeek = lastDayOfWeek.Increment
'Find the date of the last day of the week, this ensures that we get the correct week number value
dateValue = GetWeekendingDate(dateValue, lastDayOfWeek)
'Return the value of the week for the last day of the week
Return cal.GetWeekOfYear(dateValue, rule, firstDayOfWeek)
End Function


''' <summary>
''' Finds the week ending date for a specified date value
''' </summary>
''' <param name="dateValue">The date to find the week ending date for</param>
''' <param name="lastDayOfWeek">The last day of the week</param>
''' <returns>A date value that is the last day of the week that contains the specified dateValue</returns>
''' <remarks></remarks>
Public Shared Function GetWeekendingDate(ByVal dateValue As DateTime, ByVal lastDayOfWeek As DayOfWeek) As DateTime
'Find out how many days difference from the date we are testing to the end of the week
Dim dayOffset As Integer = lastDayOfWeek - cal.GetDayOfWeek(dateValue)
If dayOffset < 0 Then dayOffset += 7
'Add days to the test date so that it is the last day of the week
Return dateValue.AddDays(dayOffset)
End Function

此代码使用此扩展方法,可以快速查找一周中的第二天:

<Extension()>
Public Function Increment(ByVal aDay As DayOfWeek) As DayOfWeek
Select Case aDay
Case DayOfWeek.Sunday : Return DayOfWeek.Monday
Case DayOfWeek.Monday : Return DayOfWeek.Tuesday
Case DayOfWeek.Tuesday : Return DayOfWeek.Wednesday
Case DayOfWeek.Wednesday : Return DayOfWeek.Thursday
Case DayOfWeek.Thursday : Return DayOfWeek.Friday
Case DayOfWeek.Friday : Return DayOfWeek.Saturday
Case DayOfWeek.Saturday : Return DayOfWeek.Sunday
Case Else : Return Nothing
End Select
End Function

我用这个尝试了你的测试用例并得到了以下结果:

Debug.WriteLine(GetIso8601WeekOfYear(Date.Parse("20/07/2015"))) '30
Debug.WriteLine(GetIso8601WeekOfYear(Date.Parse("09/03/2015"))) '11
Debug.WriteLine(GetIso8601WeekOfYear(Date.Parse("29/12/2014"))) '1
Debug.WriteLine(GetIso8601WeekOfYear(Date.Parse("05/01/2015"))) '2
Debug.WriteLine(GetIso8601WeekOfYear(Date.Parse("30/12/2013"))) '1
Debug.WriteLine(GetIso8601WeekOfYear(Date.Parse("06/01/2014"))) '2

关于.net - 使用 DatePart() 的 ISO8601 周数不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31560905/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com