Datetime - Получить следующий вторник - PullRequest
135 голосов
/ 14 июня 2011

Как я могу получить дату следующего вторника?

В PHP это так же просто, как strtotime('next tuesday');.

Как мне добиться чего-то похожего в .NET

Ответы [ 10 ]

330 голосов
/ 14 июня 2011

Как я уже упоминал в комментариях, есть несколько вещей, которые вы можете подразумевать под «следующим вторником», но этот код дает вам «следующий вторник или сегодня, если уже вторник»:

DateTime today = DateTime.Today;
// The (... + 7) % 7 ensures we end up with a value in the range [0, 6]
int daysUntilTuesday = ((int) DayOfWeek.Tuesday - (int) today.DayOfWeek + 7) % 7;
DateTime nextTuesday = today.AddDays(daysUntilTuesday);

Если вы хотите указать «недельное время», если уже вторник, вы можете использовать:

// This finds the next Monday (or today if it's Monday) and then adds a day... so the
// result is in the range [1-7]
int daysUntilTuesday = (((int) DayOfWeek.Monday - (int) today.DayOfWeek + 7) % 7) + 1;

... или вы можете использовать оригинальную формулу, но с завтрашнего дня:

DateTime tomorrow = DateTime.Today.AddDays(1);
// The (... + 7) % 7 ensures we end up with a value in the range [0, 6]
int daysUntilTuesday = ((int) DayOfWeek.Tuesday - (int) tomorrow.DayOfWeek + 7) % 7;
DateTime nextTuesday = tomorrow.AddDays(daysUntilTuesday);

РЕДАКТИРОВАТЬ: Просто, чтобы сделать это красиво и универсально:

public static DateTime GetNextWeekday(DateTime start, DayOfWeek day)
{
    // The (... + 7) % 7 ensures we end up with a value in the range [0, 6]
    int daysToAdd = ((int) day - (int) start.DayOfWeek + 7) % 7;
    return start.AddDays(daysToAdd);
}

Таким образом, чтобы получить значение для «сегодня или в ближайшие 6 дней»:

DateTime nextTuesday = GetNextWeekday(DateTime.Today, DayOfWeek.Tuesday);

Чтобы получить значение для «следующий вторник, исключая сегодня»:

DateTime nextTuesday = GetNextWeekday(DateTime.Today.AddDays(1), DayOfWeek.Tuesday);
60 голосов
/ 14 июня 2011

Это должно сработать:

static DateTime GetNextWeekday(DayOfWeek day)
{
    DateTime result = DateTime.Now.AddDays(1);
    while( result.DayOfWeek != day )
        result = result.AddDays(1);
    return result;
}
7 голосов
/ 25 января 2013

Существует менее многословное и более умное / элегантное решение этой проблемы, но следующая функция C # действительно хорошо работает для ряда ситуаций.

5 голосов
/ 14 июня 2011
DateTime nextTuesday = DateTime.Today.AddDays(((int)DateTime.Today.DayOfWeek - (int)DayOfWeek.Tuesday) + 7);
4 голосов
/ 07 января 2015

@ Джон Скит хороший ответ.

За предыдущий день:

private DateTime GetPrevWeekday(DateTime start, DayOfWeek day) {
    // The (... - 7) % 7 ensures we end up with a value in the range [0, 6]
    int daysToRemove = ((int) day - (int) start.DayOfWeek - 7) % 7;
    return start.AddDays(daysToRemove);
}

Спасибо !!

4 голосов
/ 14 июня 2011
DateTime nexttuesday=DateTime.Today.AddDays(1);

while(nexttuesday.DayOfWeek!=DayOfWeek.Tuesday)
   nexttuesday = nexttuesday.AddDays(1);
2 голосов
/ 07 марта 2019

Очень простой образец для включения или исключения текущей даты, вы указываете дату и день недели, в которую вы заинтересованы.

public static class DateTimeExtensions
{
    /// <summary>
    /// Gets the next date.
    /// </summary>
    /// <param name="date">The date to inspected.</param>
    /// <param name="dayOfWeek">The day of week you want to get.</param>
    /// <param name="exclDate">if set to <c>true</c> the current date will be excluded and include next occurrence.</param>
    /// <returns></returns>
    public static DateTime GetNextDate(this DateTime date, DayOfWeek dayOfWeek, bool exclDate = true)
    {
        //note: first we need to check if the date wants to move back by date - Today, + diff might move it forward or backwards to Today
        //eg: date - Today = 0 - 1 = -1, so have to move it forward
        var diff = dayOfWeek - date.DayOfWeek;
        var ddiff = date.Date.Subtract(DateTime.Today).Days + diff;

        //note: ddiff < 0 : date calculates to past, so move forward, even if the date is really old, it will just move 7 days from date passed in
        //note: ddiff >= (exclDate ? 6 : 7) && diff < 0 : date is into the future, so calculated future weekday, based on date
        if (ddiff < 0 || ddiff >= (exclDate ? 6 : 7) && diff < 0)
            diff += 7; 

        //note: now we can get safe values between 0 - 6, especially if past dates is being used
        diff = diff % 7;

        //note: if diff is 0 and we are excluding the date passed, we will add 7 days, eg: 1 week
        diff += diff == 0 & exclDate ? 7 : 0;

        return date.AddDays(diff);
    }
}

некоторые тесты

[TestMethod]
    public void TestNextDate()
    {
        var date = new DateTime(2013, 7, 15);
        var start = date;
        //testing same month - forwardOnly
        Assert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Tuesday)); //16
        Assert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Wednesday)); //17
        Assert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Thursday)); //18
        Assert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Friday)); //19
        Assert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Saturday)); //20
        Assert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Sunday)); //21
        Assert.AreEqual(start.AddDays(1), date.GetNextDate(DayOfWeek.Monday)); //22

        //testing same month - include date
        Assert.AreEqual(start = date, date.GetNextDate(DayOfWeek.Monday, false)); //15
        Assert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Tuesday, false)); //16
        Assert.AreEqual(start.AddDays(1), date.GetNextDate(DayOfWeek.Wednesday, false)); //17

        //testing month change - forwardOnly
        date = new DateTime(2013, 7, 29);
        start = date;
        Assert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Tuesday)); //30
        Assert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Wednesday)); //31
        Assert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Thursday)); //2013/09/01-month increased
        Assert.AreEqual(start.AddDays(1), date.GetNextDate(DayOfWeek.Friday)); //02

        //testing year change
        date = new DateTime(2013, 12, 30);
        start = date;
        Assert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Tuesday)); //31
        Assert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Wednesday)); //2014/01/01 - year increased
        Assert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Thursday)); //02
    }
1 голос
/ 15 февраля 2017

Это может быть также расширением, все зависит

public static class DateTimeExtensions
{
    public static IEnumerable<DateTime> Next(this DateTime date, DayOfWeek day)
    {
        // This loop feels expensive and useless, but the point is IEnumerable
        while(true)
        {
            if (date.DayOfWeek == day)
            {
                yield return date;
            }
            date = date.AddDays(1);
        }
    }
}

Использование

    var today = DateTime.Today;
    foreach(var monday in today.Next(DayOfWeek.Monday))
    {
        Console.WriteLine(monday);
        Console.ReadKey();
    }
0 голосов
/ 28 августа 2017

Объектив C Версия:

+(NSInteger) daysUntilNextWeekday: (NSDate*)startDate withTargetWeekday: (NSInteger) targetWeekday
{
    NSInteger startWeekday = [[NSCalendar currentCalendar] component:NSCalendarUnitWeekday fromDate:startDate];
    return (targetWeekday - startWeekday + 7) % 7;
}
0 голосов
/ 07 января 2016

Теперь во вкусе oneliner - в случае, если вам нужно передать его как параметр в некоторый механизм.

DateTime.Now.AddDays(((int)yourDate.DayOfWeek - (int)DateTime.Now.DayOfWeek + 7) % 7).Day

В данном конкретном случае:

DateTime.Now.AddDays(((int)DayOfWeek.Tuesday - (int)DateTime.Now.DayOfWeek + 7) % 7).Day
...