从日期时间获取周数

Get the week number from a date time

我正在尝试从日期时间获取周数,在我的例子中,一周的第一天是星期一,我想遵循 FirstFourDays 约定。

为了查看结果,我正在查看这个网页:

https://espanol.epochconverter.com/semanas/2020

要获取周数,我使用的方法是:

System.Globalization.CultureInfo.InvariantCulture.Calendar.GetWeekOfYear();

所以我试图获取日期 2019-12-29 的周数,所以我使用此代码:

System.Globalization.CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(new DateTime(2019, 12, 29), System.Globalization.CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);

结果是第 52 周,正确。

现在我想获取2019-12-30的周数,我得到的周数是53,这是错误的,因为2019年只有52周。事实上,2019-12-30 与 2020-01-01 属于同一周,即第 1 周,这是正确的,所以我不明白为什么我可以在同一日期得到两个不同的结果。

我怎样才能始终得到正确的结果?或者获取任何日期的周数的正确方法是什么?

有一个 blog article 解释了这种行为并提出了解决方案。

问题:

Several people have noticed that Calendar.GetWeekOfYear() is almost like the ISO 8601 week when passed CalendarWeekRule.FirstFourDayWeek and DayOfWeek.Monday, however it is a little bit different. Specifically ISO 8601 always has 7 day weeks. If the first partial week of a year doesn't contain Thursday, then it is counted as the last week of the previous year. Likewise, if the last week of the previous year doesn't contain Thursday then its treated like the first week of the next year. GetWeekOfYear() has the first behavior, but not the second.

建议的解决方案是这样的:

A simple workaround to consistently get the ISO 8601 week is to realize that consecutive days Monday through Sunday in ISO 8601 weeks all have the same week #. So Monday has the same week # as Thursday. Since Thursday is the critical day for determining when the week starts each year my solution is to add 3 days if the day is Monday, Tuesday or Wednesday. The adjusted days are still in the same week, and use values that GetWeekOfYear and ISO 8601 agree on.

// This presumes that weeks start with Monday.
// Week 1 is the 1st week of the year with a Thursday in it.
public static int GetIso8601WeekOfYear(DateTime time)
{
    // Seriously cheat.  If its Monday, Tuesday or Wednesday, then it'll 
    // be the same week# as whatever Thursday, Friday or Saturday are,
    // and we always get those right
    DayOfWeek day = cal.GetDayOfWeek(time);
    if (day >= DayOfWeek.Monday && day <= DayOfWeek.Wednesday)
    {
        time = time.AddDays(3);
    }

    // Return the week of our adjusted day
    return cal.GetWeekOfYear(time, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
}

所有功劳归于 Shawn Steele