WeekNumber计算.NET中的错误?

Jes*_*ann 17 .net c# date-arithmetic

我有一个相当奇怪的问题.我住在丹麦,这里2013年的第一周(第1周)开始于2012年12月31日,持续7天 - 几周通常做:)

据.NET称,12月30日是第52周,第31周是第53周,1月1日是第1周.

第53周仅持续一天,第1周持续6天.显然,这一定是错误的(一周不到7天),在丹麦语中肯定是错误的.12月31日是第1周,而不是第53周.

以下代码说明了问题(CurrentCulture是"da-DK")

    static void Main(string[] args)
    {
        //Here I get Monday
        DayOfWeek firstDayOfWeek = DateTimeFormatInfo.CurrentInfo.FirstDayOfWeek;             
        //Here I get FirstFourDayWeek
        CalendarWeekRule weekRule = DateTimeFormatInfo.CurrentInfo.CalendarWeekRule; 

        DateTime date = new DateTime(2012,12,30);

        for (int i = 0; i <= 10; i++)
        {
            DateTime currentDate = date.AddDays(i);
            Console.WriteLine("Date: {0} WeekNumber: {1}",
                currentDate.ToShortDateString(),
                CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(currentDate, weekRule, firstDayOfWeek));
        }
        Console.ReadLine();
    }
Run Code Online (Sandbox Code Playgroud)

我做错了什么或者这是.NET中的错误?如果是后者 - 您是否有正确计算周数的建议?

slo*_*oth 21

问题是该GetWeekOfYear方法不符合ISO 8601,这是您所期望的,但事实并非如此.

请注意,在您使用时FirstFourDayWeek,文档说:

基于FirstFourDayWeek值的第一周可以有四到七天.

这违反了ISO 8601规则,所有周都必须有七天.

也:

在此输入图像描述


您可以使用以下方法根据ISO 8601获取正确的周数:

int weekNumber(DateTime fromDate)
{
    // Get jan 1st of the year
    DateTime startOfYear = fromDate.AddDays(- fromDate.Day + 1).AddMonths(- fromDate.Month +1);
    // Get dec 31st of the year
    DateTime endOfYear = startOfYear.AddYears(1).AddDays(-1);
    // ISO 8601 weeks start with Monday 
    // The first week of a year includes the first Thursday 
    // DayOfWeek returns 0 for sunday up to 6 for saterday
    int[] iso8601Correction = {6,7,8,9,10,4,5};
    int nds = fromDate.Subtract(startOfYear).Days  + iso8601Correction[(int)startOfYear.DayOfWeek];
    int wk = nds / 7;
    switch(wk)
    {
        case 0 : 
            // Return weeknumber of dec 31st of the previous year
            return weekNumber(startOfYear.AddDays(-1));
        case 53 : 
            // If dec 31st falls before thursday it is week 01 of next year
            if (endOfYear.DayOfWeek < DayOfWeek.Thursday)
                return 1;
            else
                return wk;
        default : return wk;
    }
}
Run Code Online (Sandbox Code Playgroud)

来源(还有很多其他功能......)


所以,将你的循环改为

for (int i = 0; i <= 10; i++)
{
    DateTime currentDate = date.AddDays(i);
    Console.WriteLine("Date: {0} WeekNumber: {1}: CorrectWeekNumber: {2}",
        currentDate.ToShortDateString(),
        CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(currentDate, weekRule, firstDayOfWeek),
        weekNumber(currentDate));
}
Run Code Online (Sandbox Code Playgroud)

将导致:

日期:30.12.2012 WeekNumber:52:CorrectWeekNumber:52
Date:31.12.2012 WeekNumber:53:CorrectWeekNumber:1
Date:01.01.2013 WeekNumber:1:CorrectWeekNumber:1
Date:02.01.2013 WeekNumber:1:CorrectWeekNumber:1
Date: 03.01.2013 WeekNumber:1:CorrectWeekNumber:1
Date:04.01.2013 WeekNumber:1:CorrectWeekNumber:1
Date:05.01.2013 WeekNumber:1:CorrectWeekNumber:1
Date:06.01.2013 WeekNumber:1:CorrectWeekNumber:1
Date:07.01. 2013 WeekNumber:2:CorrectWeekNumber:2
Date:08.01.2013 WeekNumber:2:CorrectWeekNumber:2
Date:09.01.2013 WeekNumber:2:CorrectWeekNumber:2