Get the week number of a date in C#
This post was written in 2009. Although the logic hasn’t changed since, the implementation has. For the lastest implementation, check out NExtra on GitHub.
Background
When working with DateTime
, it’s not that straightforward to calculate the week number for a certain date. This post will present an easier approach than using Globalization
.
Note that this only works if the first weekday is Monday, the first week of a year is the one that includes the first Thursday and the last week of a year precedes the first week of the next year.
I found the original version of the function at Simen Sandelien’s personal website. The site has disappeared since then, and since I have modified the code, I chose to publish it.
/// <summary>Get the week number of a certain date, provided that
/// the first day of the week is Monday, the first week of a year
/// is the one that includes the first Thursday of that year and
/// the last week of a year is the one that immediately precedes
/// the first calendar week of the next year.
/// </summary>
/// <param name="date">Date of interest.</param>
/// <returns>The week number.</returns>
public static int GetWeekNumber(this DateTime date)
{
//Constants
const int JAN = 1;
const int DEC = 12;
const int LASTDAYOFDEC = 31;
const int FIRSTDAYOFJAN = 1;
const int THURSDAY = 4;
bool thursdayFlag = false;
//Get the day number since the beginning of the year
int dayOfYear = date.DayOfYear;
//Get the first and last weekday of the year
int startWeekDay = (int)(new DateTime(date.Year, JAN, FIRSTDAYOFJAN)).DayOfWeek;
int endWeekDay = (int)(new DateTime(date.Year, DEC, LASTDAYOFDEC)).DayOfWeek;
//Compensate for using monday as the first day of the week
if (startWeekDay == 0) {
startWeekDay = 7;
}
if (endWeekDay == 0) {
endWeekDay = 7;
}
//Calculate the number of days in the first week
int daysInFirstWeek = 8 - (startWeekDay);
//Year starting and ending on a thursday will have 53 weeks
if (startWeekDay == THURSDAY || endWeekDay == THURSDAY) {
thursdayFlag = true;
}
//We begin by calculating the number of FULL weeks between
//the year start and our date. The number is rounded up so
//the smallest possible value is 0.
int fullWeeks = (int)Math.Ceiling((dayOfYear - (daysInFirstWeek)) / 7.0);
int result = fullWeeks;
//If the first week of the year has at least four days, the
//actual week number for our date can be incremented by one.
if (daysInFirstWeek >= THURSDAY) {
result = result + 1;
}
//If the week number is larger than 52 (and the year doesn't
//start or end on a thursday), the correct week number is 1.
if (result > 52 && !thursdayFlag) {
result = 1;
}
//If the week number is still 0, it means that we are trying
//to evaluate the week number for a week that belongs to the
//previous year (since it has 3 days or less in this year).
//We therefore execute this function recursively, using the
//last day of the previous year.
if (result == 0) {
result = GetWeekNumber(new DateTime(date.Year - 1, DEC, LASTDAYOFDEC));
}
return result;
}
With this in place, getting the first and last date for a certain date’s week is easy:
/// <summary>
/// Get the first date of the week for a certain date, provided
/// that the first day of the week is Monday, the first week of
/// a year is the one that includes the first Thursday of that
/// year and the last week of a year is the one that immediately
/// precedes the first calendar week of the next year.
/// </summary>
/// <param name="date">ISO 8601 date of interest.</param>
/// <returns>The first week date.</returns>
public static DateTime GetFirstDateOfWeek(this DateTime date)
{
if (date == DateTime.MinValue) {
return date;
}
int week = date.GetWeekNumber();
while (week == date.GetWeekNumber()) {
date = date.AddDays(-1);
}
return date.AddDays(1);
}
and
/// <summary>
/// Get the last date of the week for a certain date, provided
/// that the first day of the week is Monday, the first week of
/// a year is the one that includes the first Thursday of that
/// year and the last week of a year is the one that immediately
/// precedes the first calendar week of the next year.
/// </summary>
/// <param name="date">ISO 8601 date of interest.</param>
/// <returns>The first week date.</returns>
public static DateTime GetLastDateOfWeek(this DateTime date)
{
if (date == DateTime.MaxValue) {
return date;
}
int week = date.GetWeekNumber();
while (week == date.GetWeekNumber()) {
date = date.AddDays(1);
}
return date.AddDays(-1);
}
I hope that this helps anyone having problem with retrieving the week number. If you want the latest version, check out NExtra on GitHub.