Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get the week number from a date time [duplicate]

Tags:

c#

week-number

I am trying to get the week number from a date time and in my case, the first day of the week is Monday and I want to follow the FirstFourDays convention.

To check the results, I am checking this webpage:

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

To get the week number, I using the method:

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

So I am trying to get the week number of the date 2019-12-29, so I use this code:

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

The result is week 52. It is correct.

Now I am trying to get the week number of the 2019-12-30, the week number that I get is 53, it is wrong, because 2019 has only 52 weeks. In fact, 2019-12-30 belongs to the same week than 2020-01-01, that it is week 1, that is correct, so I don't understand why I can get two different results for the same date.

How I could get the correct result always? Or how would it be the correct way to get the week number of any date?

like image 829
Álvaro García Avatar asked Oct 16 '22 08:10

Álvaro García


1 Answers

There's a blog article explaining this behavior and proposing a solution.

The issue:

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.

The proposed solution would be this:

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);
}

All credits for this go to Shawn Steele.

like image 89
Christoph Sonntag Avatar answered Oct 19 '22 22:10

Christoph Sonntag