5

I have been looking at Microsoft's documents and many stack overflow posts but none seem to answer my question. I want to know the simplest and easiest way to get an accurate week number for the current date in c#. I am pretty new to c# so please try and keep it simple. I have tried using:

int week = DateTime.Now.DayOfYear/7;
Console.WriteLine(week)

but on Monday (when I would like it to move onto the next week) it would show as the previous week. Eg: If the date was 21/12/2020 it would say the current week is the 50th, which is 2 weeks off. Then on 22/12/2020 it would say it is the 51st week, which is 1 week off.

Please Help & Thanks in advance.

TheCoder76
  • 63
  • 2
  • 6
  • 7
    What *exactly* do you mean by "week number"? There are lots of different ways of defining week numbers. – Jon Skeet Dec 22 '20 at 09:10
  • https://learn.microsoft.com/en-us/dotnet/api/system.globalization.calendar.getweekofyear?view=net-5.0 may help you... unless you want the ISO week of year, which isn't quite supported by that API. – Jon Skeet Dec 22 '20 at 09:10
  • But for ISO week-of-year, you can use https://learn.microsoft.com/en-us/dotnet/api/system.globalization.isoweek.getweekofyear?view=net-5.0 – Jon Skeet Dec 22 '20 at 09:11
  • 3
    You don't seem to take into account of the fact that January 1st isn't always a Monday – Caius Jard Dec 22 '20 at 09:12
  • 1
    Does this answer your question? [Get the correct week number of a given date](https://stackoverflow.com/questions/11154673/get-the-correct-week-number-of-a-given-date) – fdermishin Dec 22 '20 at 09:16

3 Answers3

14

This is probably what you are looking for:

DateTime dt = new DateTime(2020, 12, 21);
Calendar cal = new CultureInfo("en-US").Calendar;
int week = cal.GetWeekOfYear(dt, CalendarWeekRule.FirstDay, DayOfWeek.Monday);
Console.WriteLine(week);

You can change the CalendarWeekRule parameter to change the definition of the first week of the year:

FirstDay means that first week of the year can have any length. For example if the first day of the year was Sunday, it will be counted as week and the following Monday will be counted as part of second week.

FirstFourDayWeek means that the first week will be counted only if it mainly in this year. For example if the first day of the year will be Thursday the week will be counted, but if the year starts with Friday, the first week won't be counted.

FirstFullWeek means that the first week that will be counted will be the first full week of the year.

Bonny4
  • 271
  • 3
  • 6
  • My proposed solution below( built on this ) takes the specified culture's rules instead of declaring it your self – Marcus Pierce Jul 19 '22 at 11:58
  • Is there any way or rule to get the number of week of the specified month? – Rubio Jesús Oct 26 '22 at 14:34
  • 1
    @RubioJesús I don't think there is a rule, but you can caluclate it by substracting the week number of the first day of that month from the week number of the day (`week`, `cal` and `dt` are the same as in the answer): `week - cal.GetWeekOfYear(new DateTime(dt.Year, dt.Month, 1), ...) + 1`. The `+1` is there so that the first week in month has number 1 and not 0. – Bonny4 Oct 30 '22 at 14:48
0

I have looked at this as well when I was writing an application in LotusNotes. From what I have found, the first week of the year must contain a Thursday. If you assume that Sunday is the last day of the week, then the lowest date for Sunday has to be the 4th. With this is mind (and I am very new to C# and all the intricacies) I wrote this code which will give you the week number of any given date and also the number of weeks for this year and the previous. #

public class DateCalculations
{
    private readonly DateTime _weekDate;

    private DateTime ThisSunday => GetSundayDate(_weekDate);
    private DateTime FirstDay_ThisYear => DateTime.Parse($"01/01/{ ThisSunday.Year }");
    private DateTime FirstDay_LastYear => DateTime.Parse($"01/01/{ ThisSunday.Year - 1 }");
    private DateTime FirstDay_NextYear => DateTime.Parse($"01/01/{ ThisSunday.Year + 1 }");
    private DateTime FirstSunday_ThisYear => GetSundayDate_WeekOne(FirstDay_ThisYear);
    private DateTime FirstSunday_LastYear => GetSundayDate_WeekOne(FirstDay_LastYear);
    private DateTime FirstSunday_NextYear => GetSundayDate_WeekOne(FirstDay_NextYear);


    public DateCalculations(string weekDate)
    {
        if (DateTime.TryParse(weekDate, out _weekDate))
        {
            return;
        }
        else
        {
            throw new Exception("Incorrect date has been supplied");
        }
    }

    private bool IsDateInFirstWeek(DateTime suppliedDate)
    {
        var output = false;
        // First week must contain a Thursday, so lowest Sunday date possible is the 4th
        if (suppliedDate.Day >= 4)
        {
            output = true;
        }

        return output;
    }

    private DateTime GetSundayDate(DateTime suppliedDate)
    {
        var checkDay = suppliedDate;

        //Check if the day of the supplied date is a Sunday
        while (checkDay.DayOfWeek != DayOfWeek.Sunday)
        {
            checkDay = checkDay.AddDays(1);
        }
        return checkDay;
    }

    private DateTime GetSundayDate_WeekOne(DateTime suppliedDate)
    {
        var checkDay = GetSundayDate(suppliedDate);
        if (IsDateInFirstWeek(checkDay) == false)
        {
            checkDay = checkDay.AddDays(7);
        }

        return checkDay;
    }

    public int WeekNumber()
    {
        var output = 0;

        if (ThisSunday == FirstSunday_ThisYear)
        {
            output = 1;
        }
        else if(ThisSunday > FirstSunday_ThisYear)
        {
            TimeSpan daysBetween = ThisSunday - FirstSunday_ThisYear;
            output = (daysBetween.Days/7) + 1;
        }
        else
        {
            TimeSpan daysBetween = ThisSunday - FirstSunday_LastYear;
            output = (daysBetween.Days / 7) + 1;
        }

        return output;
    }

    public int TotalWeeksThisYear()
    {
        TimeSpan daysBetween = FirstSunday_NextYear - FirstSunday_ThisYear;

        return (daysBetween.Days / 7);
    }

    public int TotalWeeksLastYear()
    {
        TimeSpan daysBetween = FirstSunday_ThisYear - FirstSunday_LastYear;

        return (daysBetween.Days / 7);
    }
}

My console was used to test

class Program
{
    static void Main()
    {
        var test = new DateCalculations("2021-01-03");

        var weekNumber = test.WeekNumber();
        var totalWeeks = test.TotalWeeksThisYear();
        var pastWeeks = test.TotalWeeksLastYear();
        
        Console.ReadLine();
    }
}

The date format can be any string representation of a date (English or American)

Hope this helps. It may need refactoring though :)

0

Built on top of this answer: by @bunny4

But not everyone is located in the US or might have to support several cultures. Use this solution to support a cultural defined week rule and first-Day rule.. e.g. Denmark has "FirstFourDayWeek" rule for weeks and "Monday" as first day of the week.

//for now, take the the current executing thread's Culture
var cultureInfo = Thread.CurrentThread.CurrentCulture;

//let's pick a date
DateTime dt = new DateTime(2020, 12, 21);

DayOfWeek firstDay = cultureInfo.DateTimeFormat.FirstDayOfWeek;
CalendarWeekRule weekRule = cultureInfo.DateTimeFormat.CalendarWeekRule;
Calendar cal = cultureInfo.Calendar;
int week = cal.GetWeekOfYear(dt, weekRule, firstDay);
Marcus Pierce
  • 267
  • 2
  • 8