Datetime-다음 화요일에 받기


154

다음 화요일의 날짜는 어떻게 알 수 있습니까?

PHP에서는 간단합니다 strtotime('next tuesday');.

.NET에서 비슷한 것을 달성하는 방법


15
ASP.NET은 일련의 웹 기술입니다. C #은 언어입니다. 이것을 일반 .NET으로 생각해야합니다. 자, "다음 주 화요일"은 "오늘 첫 주 화요일"입니까? 월요일이고 누군가 "다음 화요일에 보자"고 말하면 1이 아닌 8 일 시간을 의미 할 것으로 예상됩니다. 오늘이 화요일이라면 어떨까요? 하루 중 몇시에 필요하십니까?
Jon Skeet 2016 년

오늘이 화요일이면 다음 화요일의 날짜를 찾고 싶습니까? 아니면 오늘은 월요일입니다. 월요일에서 두 번째 화요일을 찾으시겠습니까?
FIre Panda

가장 가까운 화요일은 어느 특정 날짜로 진행됩니다.
brenjt

2
@ brenjtL : 그리고 이미 화요일이라면?
Jon Skeet 2016 년

이미 화요일에 같은 날인 경우
brenjt

답변:


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

이미 화요일 인 경우 "1 주일"을 제공하려면 다음을 사용할 수 있습니다.

// 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

정답을 선택하기가 어려웠습니다. 그러나 당신은 가장 다재다능한 것 같고 이해하기 쉽게 만들었습니다. 도와 주셔서 감사합니다.
brenjt

1
@brenjt : 사실 난 당신이 요일을 지정할 수 스벤의가, 더 융통성이라고 말하고 싶지만,하지만 전화 : (지금은 더 일반화 된 버전을 제공하기 위해 광산을 수정했습니다.)입니다
존 소총

1
+7)%7솔루션은 그래도 꽤 좋다. 비록 내가 그것을 사용하지 않은 이유는 약간의 미세 최적화와 잘못되기가 너무 쉽기 때문에 (일부 가독성을 희생 할뿐 아니라), imho입니다.
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

67

트릭을 수행해야합니다.

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

오늘이 화요일 (ha 인 경우)이 오늘 또는 다음 화요일에 다시 반환됩니까?
brenjt

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의 확장으로 구현되는 유일한 답변입니다. 다른 솔루션은 모두 작동하지만 확장 방법으로 사용하면 사용하기 가장 쉬운 코드가 생성됩니다.
Ryan McArthur

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

오늘이 월요일 인 경우 제공 한 답변은 내일이 아니라 화요일부터 일주일이됩니다.
Tony

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

감사!!


이 솔루션은 모듈로 연산자에 전달 된 음수를 포함합니다. 모듈로 연산자에 대한 Wikipedia 기사는 말한다 "때 중 하나 또는 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

이제 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

-5

목표 C 버전 :

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

4
멋진 답변이지만 원래 질문은 .NET에 대한 질문이었습니다.
Adam Davis
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.