18

I'm in the middle of calculating week numbers for dates, but the System.Globalization.Calendar is returning odd results for (amongst other years) December 31st of year 2007 and 2012.

Calendar calendar = CultureInfo.InvariantCulture.Calendar;
var date = new DateTime(2007, 12, 29);
for (int i = 0; i < 5; i++)
{
    int w = calendar.GetWeekOfYear(date, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
    Console.WriteLine("{0}\t{1}", date.ToString("dd.MM.yyyy"), w);
    date = date.AddDays(1);
}

Results

29.12.2007      52
30.12.2007      52
31.12.2007      53 <--
01.01.2008       1
02.01.2008       1

29.12.2012      52
30.12.2012      52
31.12.2012      53 <--
01.01.2013       1
02.01.2013       1

As far as I understand, there shouldn't be a week 53 in year 2007 and 2012, but the days should be included in week 1. Is there a way to change this behaviour in the Calendar?

sshow
  • 8,820
  • 4
  • 51
  • 82

4 Answers4

16

The documentation for the CalendarWeekRule enumeration specifically states that it "does not map directly to ISO 8601", and links to ISO 8601 Week of Year format in Microsoft .Net, a blog entry that describes the differences.

Dribbel
  • 2,060
  • 2
  • 17
  • 29
phoog
  • 42,068
  • 6
  • 79
  • 117
  • This explains everything. Thanks – sshow Jan 10 '12 at 19:31
  • 9
    I don't even want to look at the workaround. My simple question is: Why? Who benefits from it? Why *slightly* change so that you have to pick two dates out of ten to see a difference? A little frustrating... – Piddu Dec 12 '12 at 14:15
  • @Piddu most likely because the team that implemented it was not aware of the standard, and after it was released, they didn't want to make a breaking change to the logic. This contrasts with the .NET implementation of Unicode, which doesn't comply with the standard because it predates the standard. (I'm not certain that ISO 8601 didn't change after the .NET logic was implemented, but the ISO standardized the calculation of week numbers in 1976, so it seems unlikely. It's also worth noting that the ISO standard reckons the beginning of the week on Monday, which conflicts with US practice.) – phoog Nov 22 '21 at 12:50
2

Have a look at the values of CalendarWeekRule. You are using FirstFourDayWeek, and so you are getting the values you describe. If you want every week to have exactly 7 days, you should use FirstFullWeek.

In your case, that would mean that 31. 12. 2007 will be week 53, but so will 2. 1. 2008.

sshow
  • 8,820
  • 4
  • 51
  • 82
svick
  • 236,525
  • 50
  • 385
  • 514
  • 1
    That solution doesn't comply with the ISO 8601, since *the first week with the majority (four or more) of its days in the starting year [is week 1]* – sshow Jan 10 '12 at 19:17
1

Starting with .net core 3 there is a new ISOWeek that actually does calculate WeekOfYear correctly

https://learn.microsoft.com/en-us/dotnet/api/system.globalization.isoweek.getweekofyear

dibs487
  • 1,294
  • 4
  • 21
  • 36
0

There don't have to be 52 weeks for the week identifiers to be unique, you just don't necessarily have 7 days in a particular week.

If this is a problem for you then add code to handle the edge case.

Guvante
  • 18,775
  • 1
  • 33
  • 64