Reputation: 1139
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
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
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
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
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
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
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
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