I have Googled a lot and found a lot of solutions, but none of them give me the correct week number for the 2012-12-31. Even the example on MSDN (link) fails.
2012-12-31 is Monday, therefore it should be Week 1, but every method I tried gives me 53. Here are some of the methods, that I have tried:
From the MDSN Library:
DateTimeFormatInfo dfi = DateTimeFormatInfo.CurrentInfo;
Calendar cal = dfi.Calendar;
return cal.GetWeekOfYear(date, dfi.CalendarWeekRule, dfi.FirstDayOfWeek);
Solution 2:
return new GregorianCalendar(GregorianCalendarTypes.Localized).GetWeekOfYear(date, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
Solution 3:
CultureInfo ciCurr = CultureInfo.CurrentCulture;
int weekNum = ciCurr.Calendar.GetWeekOfYear(dtPassed, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
return weekNum;
Update
The following method actually returns 1 when date is 2012-12-31. In other words, my problem was that my methods were not following the ISO-8601 standard.
// 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 = CultureInfo.InvariantCulture.Calendar.GetDayOfWeek(time);
if (day >= DayOfWeek.Monday && day <= DayOfWeek.Wednesday)
{
time = time.AddDays(3);
}
// Return the week of our adjusted day
return CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(time, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
}
I'm going to play Necromancer here :-)
Since there doesn't seem to be a .Net-culture that yields the correct ISO-8601 week number, I'd rather bypass the built-in week determination altogether, and do the calculation manually, instead of attempting to correct a partially correct result.
What I ended up with is the following extension method:
First of all,
((int)date.DayOfWeek + 6) % 7)
determines the weekday number, 0=monday, 6=sunday.date.AddDays(-((int)date.DayOfWeek + 6) % 7)
determines the date of the monday preceiding the requested week number.Three days later is the target thursday, which determines what year the week is in.
If you divide the (zero based) day-number within the year by seven (round down), you get the (zero based) week number in the year.
In c#, integer calculation results are round down implicitly.
As noted in this MSDN page there is a slight difference between ISO8601 week and .Net week numbering.
You can refer to this article in MSDN Blog for a better explanation: "ISO 8601 Week of Year format in Microsoft .Net"
Simply put, .Net allow weeks to be split across years while the ISO standard does not. In the article there is also a simple function to get the correct ISO 8601 week number for the last week of the year.
Update The following method actually returns 1 for
2012-12-31
which is correct in ISO 8601 (e.g. Germany).It works well both for US and Russian cultures. ISO 8601 also will be correct, `cause Russian week starts at Monday.
This is the way:
Most important for is the
CalendarWeekRule
parameter.See here: https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=IT-IT&k=k(System.Globalization.CalendarWeekRule);k(TargetFrameworkMoniker-.NETFramework
A year has 52 weeks and 1 day or 2 in case of a lap year (52 x 7 = 364). 2012-12-31 would be week 53, a week that would only have 2 days because 2012 is a lap year.