Calculating the week number is harder than it should be. Not all countries calculate week numbers equally. First you need to know when a week starts. On a sunday? or on a monday? Then you need to know what constitutes the first week of the year? At jan 1st? Or Is it the first week with at least 4 days? Or maybe even the first full week?
In my country, the week starts on a Monday, and week 1 is the first week containing at least 4 days. So with that knowledge, I can use the C# Calendar class to calculate the week number.
The Calendar class contains a GetWeekOfYear method that can be used:
using System;
using System.Globalization;
Calendar Calendar = CultureInfo.InvariantCulture.Calendar;
int weekNumber = Calendar.GetWeekOfYear(DateTime.Now, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
Console.WriteLine(weekNumber);
// May 31st, 2023 is week 22
I can now combine this knowledge into a class that can tell me more about the week, like the start date, end date, and which year the week is in. It even allows you to compare weeks and to sort them. This class is slightly complicated, but worth the trouble:
public class Week : IComparable<Week>, IEquatable<Week>
{
private const DayOfWeek FirstDayOfWeek = DayOfWeek.Monday;
private const DayOfWeek LastDayOfWeek = DayOfWeek.Sunday;
private const DayOfWeek FirstDayOfYear = DayOfWeek.Thursday;
private static readonly Calendar Calendar = CultureInfo.InvariantCulture.Calendar;
public Week(DateTime date)
{
FirstDateOfWeek = GetFirstDateOfWeek(date);
LastDateOfWeek = GetLastDateOfWeek(date);
DateTime offsetDate = GetYearOffsetDayOfWeek(FirstDateOfWeek);
WeekNumber = Calendar.GetWeekOfYear(offsetDate, CalendarWeekRule.FirstFourDayWeek, FirstDayOfWeek);
WeekYear = offsetDate.Year;
}
public DateTime FirstDateOfWeek { get; private set; }
public DateTime LastDateOfWeek { get; private set; }
public int WeekNumber { get; private set; }
public int WeekYear { get; private set; }
public int CompareTo(Week week)
{
return week == null ? -1 : string.Compare(ToString(), week.ToString(), StringComparison.Ordinal);
}
public bool Equals(Week week)
{
return week != null && string.Equals(ToString(), week.ToString(), StringComparison.Ordinal);
}
/// <summary>
/// Returns a sortable ISO week string (e.g. "2023-W22").
/// </summary>
public override string ToString()
{
return string.Format("{0}-W{1:00}", WeekYear, WeekNumber);
}
public override bool Equals(object obj)
{
return Equals(obj as Week);
}
public override int GetHashCode()
{
return ToString().GetHashCode();
}
private DateTime GetFirstDateOfWeek(DateTime date)
{
while (date.DayOfWeek != FirstDayOfWeek)
date = date.AddDays(-1);
return date;
}
private DateTime GetLastDateOfWeek(DateTime date)
{
while (date.DayOfWeek != LastDayOfWeek)
date = date.AddDays(1);
return date;
}
private DateTime GetYearOffsetDayOfWeek(DateTime firstDateOfWeek)
{
while (firstDateOfWeek.DayOfWeek != FirstDayOfYear)
firstDateOfWeek = firstDateOfWeek.AddDays(1);
return firstDateOfWeek;
}
}
To use the class:
Week week = new Week(DateTime.Now);
Console.WriteLine("Date: " + DateTime.Now.ToString("yyyy-MM-dd"));
Console.WriteLine("Week: " + week.WeekNumber);
Console.WriteLine("Starts on: " + week.FirstDateOfWeek.ToString("yyyy-MM-dd"));
Console.WriteLine("Ends on: " + week.LastDateOfWeek.ToString("yyyy-MM-dd"));
Console.WriteLine("In year: " + week.WeekYear);
// Date: 2023-05-31
// Week: 22
// Starts on: 2023-05-29
// Ends on: 2023-06-04
// In year: 2023
The slightly confusing “GetYearOffsetDayOfWeek” method is used to calculate which year the week is in. Depending of the year, a date in one year can be part of week 53 in the year before, or the other way around, dec 31st could be part of week 1 in the following year. This method moves the date forward in the week being calculated to the first day of any new year, giving the correct year of the week.
You should change the FirstDayOfWeek, LastDayOfWeek and CalendarWeekRule.FirstFourDayWeek to match the week numbering rules of your country.
That’s it. Now you are a week date expert. Happy coding.
MORE TO READ:
- CalendarWeekRule from Microsoft
- Calendar Class from Microsoft
- How to: Extract the Day of the Week from a Specific Date from Microsoft
- C# DateTime to UNIX timestamps by briancaos