14

I need to get the date of the first and last day of the week knowing the week number.

I get a start date and an end date, representing the first and last day of a selected week in a given year. then I need to get the start date and end date of the same week of the previous year to do a graphical comparison of some data.

I managed to get the week number based on the given start date and end date. Now I need to get the date of the first day and last day of the same week of the previous year. How could I do this quickest ?

EDIT: This is how I got the week number:

 private int GetWeekNumber(DateTime date)
    {
        GregorianCalendar calendar = new GregorianCalendar(GregorianCalendarTypes.USEnglish);
        return calendar.GetWeekOfYear(date, CalendarWeekRule.FirstDay, DayOfWeek.Sunday);            
    }
Octavian Epure
  • 1,019
  • 5
  • 19
  • 35

8 Answers8

30

You can use following two methods to calculate the week-number and the start-date of a given weeknumber according to a given year:

// this method is borrowed from http://stackoverflow.com/a/11155102/284240
public static int GetIso8601WeekOfYear(DateTime time)
{
    DayOfWeek day = CultureInfo.InvariantCulture.Calendar.GetDayOfWeek(time);
    if (day >= DayOfWeek.Monday && day <= DayOfWeek.Wednesday)
    {
        time = time.AddDays(3);
    }

    return CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(time, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
} 

public static DateTime FirstDateOfWeek(int year, int weekOfYear, System.Globalization.CultureInfo ci)
{
    DateTime jan1 = new DateTime(year, 1, 1);
    int daysOffset = (int)ci.DateTimeFormat.FirstDayOfWeek - (int)jan1.DayOfWeek;
    DateTime firstWeekDay = jan1.AddDays(daysOffset);
    int firstWeek = ci.Calendar.GetWeekOfYear(jan1, ci.DateTimeFormat.CalendarWeekRule, ci.DateTimeFormat.FirstDayOfWeek);
    if ((firstWeek <= 1 || firstWeek >= 52) && daysOffset >= -3)
    {
        weekOfYear -= 1;
    }
    return firstWeekDay.AddDays(weekOfYear * 7);
}

Then you can get both dates in the following way:

// 46
int thisWeekNumber = GetIso8601WeekOfYear(DateTime.Today); 
// 11/11/2013  
DateTime firstDayOfWeek= FirstDateOfWeek(2013, thisWeekNumber, CultureInfo.CurrentCulture); 
// 11/12/2012  
DateTime firstDayOfLastYearWeek = FirstDateOfWeek(2012, thisWeekNumber, CultureInfo.CurrentCulture);   

Add 6 days to get the end of the week.

Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
  • how could I make this work for the US Calendar, where Sunday is the first day of week ? Is this as simple as replacing all references to DayOfWeek.Monday with DayOfWeek.Sunday ? – Octavian Epure Nov 11 '13 at 08:39
  • @OctavianEpure: That method returns the week number according to [ISO 8601](http://en.wikipedia.org/wiki/ISO_8601). But if you have already a method to get the week-number you just need my second method which supports a `CultureInfo` as parameter. Just pass `CultureInfo.CurentCulture` or `CultureInfo.CreateSpecificCulture("en-US")`. I have just shown my method to retrieve the week number since you haven't showed yours. – Tim Schmelter Nov 11 '13 at 08:47
  • I vave shown my method to get week number in my edited answer. Thank you very much for your post. I will try it out as soon as I start overall testing. – Octavian Epure Nov 11 '13 at 09:00
  • 2
    This method fails for 1st week of 2006. I've tested the following correction against 2012-01 until 2025-52 range. `if ((firstWeek <= 1 || firstWeek >= 52) && daysOffset >= -3)` – mnieto Mar 10 '16 at 14:19
  • hi given today, how to get the first date of week – Transformer Mar 01 '17 at 21:33
  • I was getting wrong answer for 2/25/22, was returning 2/27/22 not 2/20/22 as expected – sobelito Apr 14 '22 at 09:40
27

This is my solution:

public static DateTime FirstDayOfWeek(DateTime date)
{
    DayOfWeek fdow = CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek;
    int offset = fdow - date.DayOfWeek;
    DateTime fdowDate = date.AddDays(offset);
    return fdowDate;
}

public static DateTime LastDayOfWeek(DateTime date)
{
    DateTime ldowDate = FirstDayOfWeek(date).AddDays(6);
    return ldowDate;
}
ataravati
  • 8,891
  • 9
  • 57
  • 89
Dirk Schmidt
  • 307
  • 3
  • 3
2

The method above calculates first date wrong for 1st week of 2016.

Fixed code based on previous answers

 public DateTime FirstDateOfWeek(
        int year,
        int weekOfYear)
    {
        var newYear = new DateTime(year, 1, 1);
        var weekNumber = newYear.GetIso8601WeekOfYear(); 

        DateTime firstWeekDate;

        if (weekNumber != 1)
        {
            var dayNumber = (int) newYear.DayOfWeek;
            firstWeekDate = newYear.AddDays(7 - dayNumber + 1);
        }
        else
        {
            var dayNumber = (int)newYear.DayOfWeek;
            firstWeekDate = newYear.AddDays(-dayNumber + 1);
        }

        if (weekOfYear == 1)
        {
            return firstWeekDate;
        }

        return firstWeekDate.AddDays(7 * (weekOfYear - 1));
    }

Plus test

    [TestCase(2016, 1, 2016, 1, 4)]
    [TestCase(2016, 2, 2016, 1, 11)]
    [TestCase(2016, 52, 2016, 12, 26)]
    [TestCase(2014, 1, 2013, 12, 30)]
    public void FirstDateOfWeek_ShouldReturnCorrectDay(int year, int weekNumber, int correctYear, int correctMonth, int correctDay)
    {
        var helper = new DateHelper();
        var result = helper.FirstDateOfWeek(year, weekNumber);

        Assert.That(result.Year, Is.EqualTo(correctYear));
        Assert.That(result.Month, Is.EqualTo(correctMonth));
        Assert.That(result.Day, Is.EqualTo(correctDay));
    }
1
    private static DateTime FirstDateOfWeek(int year, int weekOfYear)
    {
        var firstDate = new DateTime(year, 1, 4);
        //first thursday of the week defines the first week (https://en.wikipedia.org/wiki/ISO_8601)
        //Wiki: the 4th of january is always in the first week
        while (firstDate.DayOfWeek != DayOfWeek.Monday)
            firstDate = firstDate.AddDays(-1);

        return firstDate.AddDays((weekOfYear - 1)*7);
    }

Easyer and more efficient solution!

Oswald
  • 1,252
  • 20
  • 32
0

Subtract 1 year from your original DateTime and call your GetWeekNumber method again with that.

TimeSpan oneYear = dateTime.AddYears(1) - dateTime;
var lastYearWeekNumber = GetWeekNumber(dateTime.Subtract(oneYear));
atomaras
  • 2,468
  • 2
  • 19
  • 28
0

You can find the solution for how to get the first and last date of the current or last week as per the passed argument date and now you can also get the date of the first day and last day of the same week of the previous year.

You can also change some settings to change your first weekday to get results as your need.

Suppose your weekday starts from Monday except for Sunday, so what you need to do is that just change the switch cases and go on to get your desired result.

public DateTime GetFirstDateOfCurrentWeek(DateTime dtDate)
{
 //In this function we assumed that week start from sunday and end on saturday
    int no = 0;
    switch (dtDate.DayOfWeek.ToString())
    {
        case "Sunday":
            no = 0;
            break;
        case "Monday":
            no = 1;
            break;
        case "Tuesday":
            no = 2;
            break;
        case "Wednesday":
            no = 3;
            break;
        case "Thursday":
            no = 4;
            break;
        case "Friday":
            no = 5;
            break;
        case "Saturday":
            no = 6;
            break;
        default:
            no = 0;
            break;
    }
    return dtDate.AddDays(-no);
 }

public DateTime GetLastDateOfCurrentWeek(DateTime dtDate)
{
    int no = 0;
    switch (dtDate.DayOfWeek.ToString())
    {
        case "Saturday":
            no = 0;
            break;
        case "Friday":
            no = 1;
            break;
        case "Thursday":
            no = 2;
            break;
        case "Wednesday":
            no = 3;
            break;
        case "Tuesday":
            no = 4;
            break;
        case "Monday":
            no = 5;
            break;
        case "Sunday":
            no = 6;
            break;
        default:
            no = 0;
            break;
    }
    return dtDate.AddDays(no);
}

public DateTime GetFirstDateOfLastWeek(DateTime dtDate)
{
    return GetFirstDateOfCurrentWeek(dtDate).AddDays(-7);
}

public DateTime GetLastDateOfLastWeek(DateTime dtDate)
{
    return GetLastDateOfCurrentWeek(dtDate).AddDays(-7);
}

public DateTime GetFirstDateOfCurrentWeekOfPrvYear(DateTime dtDate)
{
    int dayOfYear = dtDate.DayOfYear;
    DateTime firstDateOfThisYear = (Convert.ToDateTime("01/01/" + dtDate.Year.ToString()));
    DateTime firstDateofPrvYear = (firstDateOfThisYear.AddYears(-1));
    DateTime dateOfPrvYear = (firstDateofPrvYear.AddDays(dayOfYear));

    return GetFirstDateOfCurrentWeek(dateOfPrvYear);
}

public DateTime GetLastDateOfCurrentWeekOfPrvYear(DateTime dtDate)
{
    int dayOfYear = dtDate.DayOfYear;
    DateTime firstDateOfThisYear = Convert.ToDateTime("01/01/" + dtDate.Year.ToString());
    DateTime firstDateofPrvYear = (firstDateOfThisYear.AddYears(-1));
    DateTime dateOfPrvYear = (firstDateofPrvYear.AddDays(dayOfYear));

    return GetLastDateOfCurrentWeek(dateOfPrvYear);
}

DateTime dt = Convert.ToDateTime("12/12/2019");

int dayOfYear = dt.DayOfYear;
string weekOfYear = (dt.DayOfYear / 7).ToString();
string firstDateOfThisYear = (Convert.ToDateTime("01/01/" + dt.Year.ToString())).ToShortDateString();
string firstDateofPrvYear = (Convert.ToDateTime(firstDateOfThisYear).AddYears(-1)).ToShortDateString();
string dateOfPrvYear = (Convert.ToDateTime(firstDateofPrvYear).AddDays(dayOfYear)).ToShortDateString();
string firstDateofWeekPrvYear = GetFirstDateOfCurrentWeek(Convert.ToDateTime(dateOfPrvYear)).ToShortDateString();
string lastDateofWeekPrvYear = GetLastDateOfCurrentWeek(Convert.ToDateTime(dateOfPrvYear)).ToShortDateString();
string weekOfPrvYear = (Convert.ToDateTime(dateOfPrvYear).DayOfYear / 7).ToString();

MessageBox.Show("Day of Year: " + dayOfYear.ToString());
MessageBox.Show("Week of Year: " + weekOfYear);
MessageBox.Show("First day of this year: " + firstDateOfThisYear);
MessageBox.Show("First day of prv year: " + firstDateofPrvYear);
MessageBox.Show("Date of Prv Year: " + dateOfPrvYear);
MessageBox.Show("First Date of Week Prv Year: " + firstDateofWeekPrvYear);
MessageBox.Show("Last Date of Week Prv Year: " + lastDateofWeekPrvYear);
MessageBox.Show("Day of Prv Year: " + weekOfPrvYear.ToString());
Pankaj Lahoti
  • 2,792
  • 1
  • 7
  • 8
-1

Since there are 7 days per week, you will know that Week 10 is the same as days 71 - 77. You know the number of days per month (don't forget leap year). Construct the exact dates and then, you can get information about those days.

user1646737
  • 169
  • 7
  • 3
    Are you sure about that? What happens if the first of january is on a Friday? – Jonas W Nov 11 '13 at 08:24
  • Presumably, the OP knows this because he says he can get the week number. To be able to do that, I assume he had to know when the first week started. On the flip-side, you can find out the day of the week for January 1 of any given year. Then, you need to set the rule: Is this your first week, or do you need to go to the next Monday to start the first week? – user1646737 Nov 11 '13 at 08:27
  • Somebody care to explain the down-vote? If OP knows he is in week 43, then obviously, he needs to know that Friday, January 1, is either the 1st week of the year or the 2nd week, depending on whatever rule he desires to establish and follow. The rest is just math. – user1646737 Nov 11 '13 at 09:03
-1

Tim Schmelter's method didn't work for Swedish (sv-SE) culture where weeks start on Mondays. This has been tested with en-US and sv-SE.

    public static DateTime GetFirstDateOfWeek(int year, int weekOfYear, CultureInfo cultureInfo)
    {
        DateTime jan1 = new DateTime(year, 1, 1);
        int daysOffset = (int)cultureInfo.DateTimeFormat.FirstDayOfWeek - (int)jan1.DayOfWeek;
        DateTime firstWeekDay = jan1.AddDays(daysOffset);
        int firstWeek = cultureInfo.Calendar.GetWeekOfYear(jan1, cultureInfo.DateTimeFormat.CalendarWeekRule, cultureInfo.DateTimeFormat.FirstDayOfWeek);
        if (firstWeek == 1)
        {
            weekOfYear -= 1;
        }
        return firstWeekDay.AddDays(weekOfYear * 7);
    }