Henryk
Henryk

Reputation: 1139

Calculate previous week's start and end date

What is the best way to calculate the previous week's start and end date in C#? I.e. today 18 March would result in 9 March (Monday last week) and 15 March (Sunday last week).

I have seen this done with DayOfWeek and a switch statement to work out an offset but was wondering whether there is a more elegant way.

Upvotes: 49

Views: 67068

Answers (7)

John M
John M

Reputation: 101

You could create a DateTime Extension method, that can be used with a DayOfWeek parameter:

public static class DateTimeExtension
{
    public static DateTime GetPreviousWeekDay(this DateTime currentDate, DayOfWeek dow)
    {
        int currentDay = (int)currentDate.DayOfWeek, gotoDay = (int)dow;
        return currentDate.AddDays(-7).AddDays(gotoDay-currentDay);
    }        
}

Then use it as follows:

DateTime testDate = new DateTime(2017, 01, 21);
        
Console.WriteLine(testDate.GetPreviousWeekDay(DayOfWeek.Sunday));
Console.WriteLine(testDate.GetPreviousWeekDay(DayOfWeek.Saturday));

To use it to get the previous week from the current date (as asked in the question):

var prevWkStartDate = DateTime.Now.GetPreviousWeekDay(DayOfWeek.Monday); 
var prevWkEndDate = DateTime.Now.GetPreviousWeekDay(DayOfWeek.Sunday);
Console.Write($"Previous week starts at {prevWkStartDate.ToShortDateString()}");
Console.WriteLine($" and ends at {prevWkEndDate.ToShortDateString()}");

Update: Seems that this requires a fix (example date: 10th December 2020):

public static DateTime GetPreviousWeekDay(this DateTime currentDate, DayOfWeek dow)
{
    int d = 0; if (dow == DayOfWeek.Sunday) { dow = DayOfWeek.Saturday; d = 1; }
    int currentDay = (int)currentDate.DayOfWeek, gotoDay = (int)dow;
    return currentDate.AddDays(-7).AddDays(gotoDay - currentDay + d);
}

Upvotes: 3

Martin
Martin

Reputation: 113

Current accepted answer will fail for Sundays by giving the Monday of the current week instead of last weeks Monday. (code with unit tests output)

DateTime mondayOfLastWeek = date.AddDays( -(int)date.DayOfWeek - 6 );
//Failed to get start of last-week from date-time: 2020-03-01T00:00:00.0000000Z
//  Expected: 2020-02-17 00:00:00.000
//  But was:  2020-02-24 00:00:00.000

The following bit of code addresses this issue:

var dayOfWeek = (int) date.DayOfWeek - 1;
if (dayOfWeek < 0) dayOfWeek = 6;

var thisWeeksMonday = date.AddDays(-dayOfWeek).Date;
var lasWeeksMonday = thisWeeksMonday.AddDays(-7);

which can be reduced to a one-liner should you so desire (I do not recommend using this barely readable code...):

var mondayOfLastWeek  = date.AddDays(-(7 + ((int)date.DayOfWeek - 1 == -1 ? 6 : (int)date.DayOfWeek - 1)));

Upvotes: 3

nepdev
nepdev

Reputation: 977

The accepted solution is actually not correct.

You have to switch when the week "breaks", i.e. when it considers the week to end or start, and the formula in the accepted solution does not.

This is not so visible on a Monday as week start, but more so if you would consider Thursday the end of the week.

Correct formula is (for a Thursday as ending day):

DateTime thu = date.AddDays(-(int)(date.AddDays(-5).DayOfWeek) -1);

For Monday, the -5 would switch to -2.

Example code to print out

        String s = "";
        DateTime date = new DateTime(2017, 1, 1);
        for (int i = 0; i < 14; i++)
        {
            date = date.AddDays(1);
            DateTime thu = date.AddDays(-(int)(date.AddDays(-5).DayOfWeek) -1);
            DateTime mon = date.AddDays(-(int)(date.AddDays(-2).DayOfWeek) -1);
            s += date.ToString() + " - Thu: " + thu.ToString() + " - Mon: " + mon.ToString() + "\r\n";
        }
        Console.WriteLine(s);

Upvotes: 0

Simon
Simon

Reputation: 34840

using Fluent DateTime https://github.com/FluentDateTime/FluentDateTime

var dateTime = 1.Weeks().Ago();
var monday = dateTime.Previous(DayOfWeek.Sunday);
var sunday = dateTime.Next(DayOfWeek.Sunday);

Upvotes: 16

bstoney
bstoney

Reputation: 6784

You can skip the while loop and use

DateTime mondayOfLastWeek = date.AddDays( -(int)date.DayOfWeek - 6 );

This assumes you're using Monday as the first day of the week.

Upvotes: 86

Andy Rose
Andy Rose

Reputation: 16974

Using DayOfWeek would be a way of achieving this:

    DateTime date = DateTime.Now.AddDays(-7);
    while (date.DayOfWeek != DayOfWeek.Monday)
    {
        date = date.AddDays(-1);
    }

    DateTime startDate = date;
    DateTime endDate = date.AddDays(7);

Upvotes: 3

mqp
mqp

Reputation: 71945

DayOfWeek weekStart = DayOfWeek.Monday; // or Sunday, or whenever
DateTime startingDate = DateTime.Today;

while(startingDate.DayOfWeek != weekStart)
    startingDate = startingDate.AddDays(-1);

DateTime previousWeekStart = startingDate.AddDays(-7);
DateTime previousWeekEnd = startingDate.AddDays(-1);

Read: Backtrack one day at a time until we're at the start of this week, and then subtract seven to get to the start of last week.

Upvotes: 35

Related Questions