Get last/next week Wednesday date in C#

Viewed 30229

How would I get last week Wednesday and next week Wednesday's date in C#:

public Form1()
{
   InitializeComponent();
   CurrentDate.Text = "Today's Date: " + DateTime.Now.ToString("dd/MM/yyyy");
   CurrentRent.Text = "Current Rent Date: "; // last wednesday
   NextRent.Text = "Next Rent Date: "; // next wednesday
}
13 Answers

To find the next Wednesday just keep adding days until you find one. To find the previous Wednesday just keep subtracting days until you get to one.

DateTime nextWednesday = DateTime.Now.AddDays(1);
while (nextWednesday.DayOfWeek != DayOfWeek.Wednesday)
    nextWednesday = nextWednesday.AddDays(1);
DateTime lastWednesday = DateTime.Now.AddDays(-1);
while (lastWednesday.DayOfWeek != DayOfWeek.Wednesday)
    lastWednesday = lastWednesday.AddDays(-1);

Use the AddDays routine:

        // increment by the number of offset days to get the correct date
        DayOfWeek desiredDay = DayOfWeek.Wednesday;
        int offsetAmount = (int) desiredDay - (int) DateTime.Now.DayOfWeek;
        DateTime lastWeekWednesday = DateTime.Now.AddDays(-7 + offsetAmount);
        DateTime nextWeekWednesday = DateTime.Now.AddDays(7 + offsetAmount);

That should do it!

NOTE: If it is a Monday, "Last Wednesday" is going to give you the very last Wednesday that occurred, but "Next Wednesday" is going to give you the Wednesday 9 days from now! If you wanted to get the Wednesday in two days instead you would need to use the "%" operator. That means the second "nextweek" statement would read "(7 + offsetAmount) % 7".

DateTime.Now.AddDays(7) and DateTime.Now.AddDays(-7) is how you can do arithmetic, assuming you are on Wednesday. If you aren't, what you would need to do is use the DayOfWeek property to determine the number of days (positive and negative) that you would need to determine which day is 'Wednesday'. Then you can pass that value into AddDays.

For instance, if today was tuesday, you would AddDays(-6) for last Wednesday and AddDays(8) for next Wednesday.

I'll leave you the task of calculating those.

You can use this to calculate it:

DateTime day = DateTime.Today;
while (day.DayOfWeek != DayOfWeek.Wednesday)
    day = day.AddDays(-1);
var currentRent = day;
var nextRent = day.AddDays(7);

Note that if today is Wednesday, this will show currentRent as today, not nextRent as today. If you want this reversed, you can reverse the logic.

DateTime day = DateTime.Today;
while (day.DayOfWeek != DayOfWeek.Wednesday)
    day = day.AddDays(1);
var currentRent = day.AddDays(-7);
var nextRent = day;

This will work. You need to calculate the difference in days between your provided date and the nearest Wednesday, and calculate last/next Wednesday based on whether or not the difference is greater than zero.

int difference = date.DayOfWeek - DayOfWeek.Wednesday;
DateTime lastWednesday = difference > 0 ? date.AddDays(-1 * difference) : date.AddDays(-1 * (7 + difference));
DateTime nextWednesday = lastWednesday.AddDays(7);

Based on Servy's answer, here's an extension method which will return the desired day/date:

    public static DateTime GetPrevious(this DateTime date, DayOfWeek dayOfWeek)
    {
        var lastDay = date.AddDays(-1);
        while (lastDay.DayOfWeek != dayOfWeek)
        {
            lastDay = lastDay.AddDays(-1);
        }

        return lastDay;
    }

    public static DateTime GetNext(this DateTime date, DayOfWeek dayOfWeek)
    {
        var nextDay = date.AddDays(+1);
        while (nextDay.DayOfWeek != dayOfWeek)
        {
            nextDay = nextDay.AddDays(+1);
        }

        return nextDay;
    }

You'll want to use the DayOfWeek enum along with an if-else structure of switch statement to determine how many days to add/subtract for your dates. It's tedious coding but simple.

DateTime nextRent;
DateTime lastRent;
DateTime today = DateTime.Now;

if (today.DayOfWeek == DayOfWeek.Wednesday)
{
   nextRent = today.AddDays(7);
   lastRent = today.AddDays(-7);
}
else if (today.DayOfWeek == DayOfWeek.Thursday)
{
   nextRent = today.AddDays(6);
   lastRent = today.AddDays(-8);
}
//ect for all days

Here is a one-liner to accomplish the same. It is somewhat mind-boggling to understand how that actually works but it does:

Getting next Wednesday:

 dt.AddDays(-(int)(dt.AddDays(-4).DayOfWeek) + 6);

Getting last Wednesday

 dt.AddDays(-(int)(dt.AddDays(-3).DayOfWeek));

In both cases, it will return the day itself when it is Wednesday. This works for any weekdays, just adjust the number in the AddDays() call. For example for Friday:

Getting next Friday

 dt.AddDays(-(int)(dt.AddDays(-6).DayOfWeek) + 6);

Getting last Friday

 dt.AddDays(-(int)(dt.AddDays(-5).DayOfWeek));

One of the problems with some of the answers is that the DayoyOfWeek is an enum with values 0-6. When a subsequent day of week equates to Sunday (enum value = 0), but you gave a Tuesday (enum value=2), and you want next tuesday, the calculation goes wrong if you just peform a calculation.

The class with two methods which I cam up with for my own use on a project I am working on is.

public static class DateHelper
{
    public static DateTime GetDateForLastDayOfWeek(DayOfWeek DOW, DateTime DATE)
    {
        int adjustment = ((int)DATE.DayOfWeek < (int)DOW ? 7 : 0);
        return DATE.AddDays(0- (((int)(DATE.DayOfWeek) + adjustment) - (int)DOW));
    }

    public static DateTime GetDateForNextDayOfWeek(DayOfWeek DOW, DateTime DATE)
    {
        int adjustment = ((int)DATE.DayOfWeek < (int)DOW ? 0 : 7);
        return DATE.AddDays(((int)DOW) - ((int)(DATE.DayOfWeek)) + adjustment);
    }
}

The XUnit tests proving the code above works.

public class DateHelperUnitTests
{

    [Theory]
    [InlineData(2020, 1, 7, 2020, 1, 7)]
    [InlineData(2020, 1, 8,  2020, 1, 7)]
    [InlineData(2020, 1, 9,  2020, 1, 7)]
    [InlineData(2020, 1, 10, 2020, 1, 7)]
    [InlineData(2020, 1, 11, 2020, 1, 7)]
    [InlineData(2020, 1, 12, 2020, 1, 7)]
    [InlineData(2020, 1, 13, 2020, 1, 7)]
    [InlineData(2020, 1, 14, 2020, 1, 14)]
    [InlineData(2020, 1, 15, 2020, 1, 14)]
    public void GetDateForLastDayOfWeek_MultipleValues_Pass(
        int InputYear, int InputMonth, int InputDay,
        int ExpectedYear, int ExpectedMonth, int ExpectedDay)
    {
        DateTime DateToTest = new DateTime(InputYear, InputMonth, InputDay);
        DateTime NewDate = DateHelper.GetDateForLastDayOfWeek(DayOfWeek.Tuesday, DateToTest);
        DateTime DateExpected = new DateTime(ExpectedYear,ExpectedMonth,ExpectedDay);

        Assert.True(0 == DateTime.Compare(DateExpected.Date, NewDate.Date));
    }

    [Theory]
    [InlineData(2020, 1, 7, 2020, 1, 14)]
    [InlineData(2020, 1, 8, 2020, 1, 14)]
    [InlineData(2020, 1, 9, 2020, 1, 14)]
    [InlineData(2020, 1, 10, 2020, 1, 14)]
    [InlineData(2020, 1, 11, 2020, 1, 14)]
    [InlineData(2020, 1, 12, 2020, 1, 14)]
    [InlineData(2020, 1, 13, 2020, 1, 14)]
    [InlineData(2020, 1, 14, 2020, 1, 21)]
    [InlineData(2020, 1, 15, 2020, 1, 21)]
    public void GetDateForNextDayOfWeek_MultipleValues_Pass(
        int InputYear, int InputMonth, int InputDay,
        int ExpectedYear, int ExpectedMonth, int ExpectedDay)
    {
        DateTime DateToTest = new DateTime(InputYear, InputMonth, InputDay);
        DateTime NewDate = DateHelper.GetDateForNextDayOfWeek(DayOfWeek.Tuesday, DateToTest);
        DateTime DateExpected = new DateTime(ExpectedYear, ExpectedMonth, ExpectedDay);

        Assert.True(0 == DateTime.Compare(DateExpected.Date, NewDate.Date));
    }
}

this extension method should do the trick for whatever dayofweek

   public static class DateTimeExtensions
    {
        public static DateTime LastDayOfWeek(this DateTime _date, DayOfWeek dayofweek)
        {
            return _date.AddDays(-1 * ((_date.DayOfWeek - dayofweek) % 7)).Date;
        }

        public static DateTime NextDayOfWeek(this DateTime _date, DayOfWeek dayofweek)
        {
            return _date.LastDayOfWeek(dayofweek).AddDays(7).Date;
        }
    }

usage

var lastWendsday = DateTime.Now.LastDayOfWeek(DayOfWeek.Wednesday);
Related