Introduction
Week number is quite complex: ISO 8601[^] specifies that weeks start on Monday, and that Jan 1st is in week one if it occurs on a Thursday, Friday, Saturday, or Sunday. Otherwise it is in the last week of the previous year, which may be week 51, 52, or 53.
Over the years, I have come up with a couple of ways of handling this, but this version uses recursion to identify the last week of the previous year, and is pretty simple to understand.
public static class ExtensionMethods
{
private static int[] moveByDays = { 6, 7, 8, 9, 10, 4, 5 };
public static int WeekOfYear(this DateTime date)
{
DateTime startOfYear = new DateTime(date.Year, 1, 1);
DateTime endOfYear = new DateTime(date.Year, 12, 31);
int numberDays = date.Subtract(startOfYear).Days +
moveByDays[(int) startOfYear.DayOfWeek];
int weekNumber = numberDays / 7;
switch (weekNumber)
{
case 0:
weekNumber = WeekOfYear(startOfYear.AddDays(-1));
break;
case 53:
if (endOfYear.DayOfWeek < DayOfWeek.Thursday)
{
weekNumber = 1;
}
break;
}
return weekNumber;
}
}
It works by calculating the number of days since the start of the year, and moving that forward by a week to get a one-based answer. This is offset back a week, if the start of the year is a Monday, Tuesday or Wednesday, and adjusted for the DateTime.DayOfWeek
return of Sunday as the week start - hence the odd numbering of the moveByDays
array elements.