日期时间-获取下一个星期二


154

如何获得下周二的日期?

在PHP中,它非常简单strtotime('next tuesday');

如何在.NET中实现类似的目标


15
ASP.NET是一组Web技术。C#是一种语言。您确实需要从纯.NET角度考虑这一点。现在,对于“下一个星期二”-是“今天之后的第一个星期二”吗?如果是星期一,并且有人说“下周二见”,我希望这意味着8天而不是1天。今天是星期二呢?您需要什么时间?
乔恩·斯基特

如果今天是星期二,您想查找下个星期几的日期?还是今天是星期一,您要查找星期一的第二个星期二?
FIre Panda

最接近星期二的那个星期几。
brenjt 2011年

2
@brenjtL:如果已经是星期二?
乔恩·斯基特

如果已经是星期二,那么当天
布伦特2011年

Answers:


371

正如我在评论中所提到的,“下一个星期二”可能意味着多种含义,但是此代码为您提供了“下一个星期二发生,或者如果今天已经是星期二,则今天发生”:

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);

哇,我只是想知道到下个星期二我怎么能得到第n天,然后您用示例尼斯更新了答案。谢谢
brenjt 2011年

很难选择正确的答案。但是您的功能似乎最全,而且您也很容易理解。感谢您的帮助。
brenjt 2011年

1
@brenjt:实际上,我想说的是Sven更具通用性,因为您可以指定星期几,但这是您的要求:)(我现在编辑了我的以便提供更通用的版本。)
Jon Skeet

1
+7)%7解决方案虽然很好。尽管我之所以不使用它,是因为它有些微优化,而且很容易出错(并且牺牲了一些可读性),恕我直言。
斯文(Sven)

单元测试:[TestMethod] public void ShouldGetNextSaturday(){var now = DateTime.Now; var test = GetNextWeekday(DateTime.Today,DayOfWeek.Saturday); Assert.IsTrue(now.Day <test.Day,“预期的月份不在此处。”);Assert.IsTrue(test.DayOfWeek == DayOfWeek.Saturday,“预期的工作日不在这里。”); Assert.IsTrue((test.Day-now.Day)<7,“预期的日期间隔不在此处。”); }
rasx 2012年

67

这应该可以解决问题:

static DateTime GetNextWeekday(DayOfWeek day)
{
    DateTime result = DateTime.Now.AddDays(1);
    while( result.DayOfWeek != day )
        result = result.AddDays(1);
    return result;
}

很好的回应,如果今天是星期二(它是ha),今天还是下个星期二返回?
brenjt 2011年

3
这将在下一个星期二返回。如果您希望它今天返回,只需.AddDays(1)从第一行中删除,这样它也将DateTime.Now自行检查。
Sven

7

对于这个问题,没有那么冗长的解决方案,但是更聪明/更优雅的解决方案,但是下面的C#函数在许多情况下确实很好用。

/// <summary>
/// Find the closest weekday to the given date
/// </summary>
/// <param name="includeStartDate">if the supplied date is on the specified day of the week, return that date or continue to the next date</param>
/// <param name="searchForward">search forward or backward from the supplied date. if a null parameter is given, the closest weekday (ie in either direction) is returned</param>
public static DateTime ClosestWeekDay(this DateTime date, DayOfWeek weekday, bool includeStartDate = true, bool? searchForward=true)
{
    if (!searchForward.HasValue && !includeStartDate) 
    {
        throw new ArgumentException("if searching in both directions, start date must be a valid result");
    }
    var day = date.DayOfWeek;
    int add = ((int)weekday - (int)day);
    if (searchForward.HasValue)
    {
        if (add < 0 && searchForward.Value)
        {
            add += 7;
        }
        else if (add > 0 && !searchForward.Value)
        {
            add -= 7;
        }
        else if (add == 0 && !includeStartDate)
        {
            add = searchForward.Value ? 7 : -7;
        }
    }
    else if (add < -3) 
    {
        add += 7; 
    }
    else if (add > 3)
    {
        add -= 7;
    }
    return date.AddDays(add);
}

1
实现为DateTime扩展的唯一答案。尽管其他解决方案都可以使用,但将其作为扩展方法可以生成最易于使用的代码。
瑞安·麦克阿瑟

5
DateTime nextTuesday = DateTime.Today.AddDays(((int)DateTime.Today.DayOfWeek - (int)DayOfWeek.Tuesday) + 7);

如果今天是星期一,则您提供的答案将从星期二开始,而不是明天开始。
托尼

5

@乔恩·斯基特(Jon Skeet)好的答案。

对于前一天:

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);
}

谢谢!!


请注意,此解决方案涉及递给模运算符的负数。在对模运算维基百科的文章说,“当A或n是负的,天真的定义发生故障和编程语言中这些值是如何定义的不同。” 尽管这可能在C#中可行,但要获得相同结果的数学上更“可靠”的解决方案将是DayOfWeek像这样交换值:int daysToSubtract = -(((int)dateTime.DayOfWeek - (int)day + 7) % 7);
Andre

4
DateTime nexttuesday=DateTime.Today.AddDays(1);

while(nexttuesday.DayOfWeek!=DayOfWeek.Tuesday)
   nexttuesday = nexttuesday.AddDays(1);

3

包含或排除当前日期的非常简单的示例,您可以指定日期和感兴趣的日期。

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
    }

经过大量测试,我对原始答案进行了其他更改。现在,这将根据使用的日期,过去,现在和将来安全地计算第二天。前面的所有示例都很棒,但是在某些情况下失败了。我并没有说它是单行的声明,因此可以对计算的内容进行其他评论。乔恩·斯凯特(Jon Skeet)的积极案例很棒,尽管我不得不将日期推迟1天,但仍然大于今天,如果它移到今天或昨天该怎么办……这解决了它。
AJB

1

可能是扩展,这完全取决于

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

现在具有单线风格-万一您需要将其作为参数传递给某种机制。

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

-5

目标C版本:

+(NSInteger) daysUntilNextWeekday: (NSDate*)startDate withTargetWeekday: (NSInteger) targetWeekday
{
    NSInteger startWeekday = [[NSCalendar currentCalendar] component:NSCalendarUnitWeekday fromDate:startDate];
    return (targetWeekday - startWeekday + 7) % 7;
}

4
很酷的答案,但最初的问题是关于.NET的。
亚当·戴维斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.