DateTime Extension Method to Give Week Number





5.00/5 (4 votes)
Strangely, the .NET DateTime does not provide a Week Number. This extension rectifies this.
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
{
/// <summary>
/// Offsets to move the day of the year on a week, allowing
/// for the current year Jan 1st day of week, and the Sun/Mon
/// week start difference between ISO 8601 and Microsoft
/// </summary>
private static int[] moveByDays = { 6, 7, 8, 9, 10, 4, 5 };
/// <summary>
/// Get the Week number of the year
/// (In the range 1..53)
/// This conforms to ISO 8601 specification for week number.
/// </summary>
/// <param name="date"></param>
/// <returns>Week of year</returns>
public static int WeekOfYear(this DateTime date)
{
DateTime startOfYear = new DateTime(date.Year, 1, 1);
DateTime endOfYear = new DateTime(date.Year, 12, 31);
// ISO 8601 weeks start with Monday
// The first week of a year includes the first Thursday
// This means that Jan 1st could be in week 51, 52, or 53 of the previous year...
int numberDays = date.Subtract(startOfYear).Days +
moveByDays[(int) startOfYear.DayOfWeek];
int weekNumber = numberDays / 7;
switch (weekNumber)
{
case 0:
// Before start of first week of this year - in last week of previous year
weekNumber = WeekOfYear(startOfYear.AddDays(-1));
break;
case 53:
// In first week of next year.
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.