ASP.NET to zestaw technologii internetowych. C # to język. Naprawdę musisz pomyśleć o tym w kategoriach zwykłego .NET. A teraz „następny wtorek” - czy to „pierwszy wtorek po dzisiejszym dniu”? Gdyby był poniedziałek i ktoś powiedziałby „do zobaczenia w przyszły wtorek”, spodziewałbym się, że będzie to oznaczać 8 dni zamiast 1. A co jeśli dzisiaj jest wtorek? O jakiej porze dnia potrzebujesz?
Jon Skeet
Jeśli dzisiaj jest wtorek, chcesz znaleźć datę, kiedy jest następny wtorek? Lub dzisiaj jest poniedziałek, chcesz znaleźć drugi wtorek od poniedziałku?
FIre Panda
Najbliższy wtorek, który kiedykolwiek się pojawił.
brenjt
2
@brenjtL: A jeśli jest już wtorek?
Jon Skeet
Jeśli już we wtorek, to tego samego dnia
brenjt
Odpowiedzi:
371
Jak wspomniałem w komentarzach, jest wiele rzeczy, które możesz rozumieć przez „następny wtorek”, ale ten kod podaje „następny wtorek, który ma nastąpić lub dzisiaj, jeśli jest już wtorek”:
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);
Jeśli chcesz podać „tydzień czasu”, jeśli jest już wtorek, możesz użyć:
// 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;
... lub możesz użyć oryginalnej formuły, ale od jutra:
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);
EDYCJA: Po prostu, aby to było ładne i wszechstronne:
publicstaticDateTimeGetNextWeekday(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);}
Aby uzyskać wartość dla „dzisiaj lub w ciągu najbliższych 6 dni”:
Wow, zastanawiałem się tylko, jak mogę uzyskać n-te dni do następnego wtorku, a następnie zaktualizowałeś swoją odpowiedź przykładem Nice. Dzięki
brenjt
Trudno było wybrać poprawną odpowiedź. Ale Twój wydaje się być najbardziej wszechstronny i ułatwiłeś zrozumienie. Dzięki za pomoc.
brenjt
1
@brenjt: Właściwie powiedziałbym, że Sven jest bardziej wszechstronny, ponieważ możesz określić dzień tygodnia, ale to twoja decyzja :) (Teraz zredagowałem moją, aby dać bardziej ogólną wersję.)
Jon Skeet
1
+7)%7Rozwiązanie jest całkiem ładna. Chociaż powodem, dla którego go nie użyłem, jest to, że jest to trochę mikro-optymalizacja i zbyt łatwo się pomylić (a także poświęcić trochę czytelności), oczywiście imho.
Sven
Test jednostkowy: [TestMethod] public void ShouldGetNextSaturday () {var now = DateTime.Now; var test = GetNextWeekday (DateTime.Today, DayOfWeek.Saturday); Assert.IsTrue (now.Day <test.Day, "Nie ma oczekiwanego dnia miesiąca."); Assert.IsTrue (test.DayOfWeek == DayOfWeek.Saturday, "Nie ma oczekiwanego dnia tygodnia."); Assert.IsTrue ((test.Day - now.Day) <7, "Nie ma oczekiwanego przedziału dziennego."); }
rasx,
67
To powinno załatwić sprawę:
staticDateTimeGetNextWeekday(DayOfWeek day){DateTime result =DateTime.Now.AddDays(1);while( result.DayOfWeek!= day )
result = result.AddDays(1);return result;}
Świetna odpowiedź, jeśli dzisiaj jest wtorek (czyli ha) to powróci dzisiaj, czy w następny wtorek?
brenjt
3
To powróci w następny wtorek. Jeśli chcesz, aby powrócił dzisiaj, po prostu usuń .AddDays(1)z pierwszej linii, w ten sposób również się sprawdzi DateTime.Now.
Sven
7
Istnieją mniej rozwlekłe i bardziej sprytne / eleganckie rozwiązania tego problemu, ale poniższa funkcja C # działa naprawdę dobrze w wielu sytuacjach.
/// <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>publicstaticDateTimeClosestWeekDay(thisDateTime date,DayOfWeek weekday,bool includeStartDate =true,bool? searchForward=true){if(!searchForward.HasValue&&!includeStartDate){thrownewArgumentException("if searching in both directions, start date must be a valid result");}var day = date.DayOfWeek;intadd=((int)weekday -(int)day);if(searchForward.HasValue){if(add<0&& searchForward.Value){add+=7;}elseif(add>0&&!searchForward.Value){add-=7;}elseif(add==0&&!includeStartDate){add= searchForward.Value?7:-7;}}elseif(add<-3){add+=7;}elseif(add>3){add-=7;}return date.AddDays(add);}
Jedyna odpowiedź, która implementuje jako rozszerzenie do DateTime. Podczas gdy wszystkie inne rozwiązania działają, użycie go jako metody rozszerzenia daje najłatwiejszy w użyciu kod.
Jeśli dzisiaj jest poniedziałek, odpowiedź, którą podałeś, będzie miała tydzień od wtorku, a nie jutro.
Tony
5
@Jon Skeet dobra odpowiedź.
Za poprzedni dzień:
privateDateTimeGetPrevWeekday(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);}
Zwróć uwagę, że to rozwiązanie obejmuje liczby ujemne przekazywane operatorowi modulo. Artykuł w Wikipedii dotyczący operatora modulo mówi, że „Gdy a lub n jest ujemne, naiwna definicja załamuje się, a języki programowania różnią się sposobem definiowania tych wartości”. Chociaż prawdopodobnie działa to w C #, matematycznie bardziej „solidnym” rozwiązaniem, aby uzyskać ten sam wynik, byłaby zamiana DayOfWeekwartości w następujący sposób:int daysToSubtract = -(((int)dateTime.DayOfWeek - (int)day + 7) % 7);
Bardzo prosta próbka do uwzględnienia lub wykluczenia aktualnej daty, określasz datę i dzień tygodnia, który Cię interesuje.
publicstaticclassDateTimeExtensions{/// <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>publicstaticDateTimeGetNextDate(thisDateTime 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 forwardvar 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 dateif(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);}}
niektóre przypadki testowe
[TestMethod]publicvoidTestNextDate(){var date =newDateTime(2013,7,15);var start = date;//testing same month - forwardOnlyAssert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Tuesday));//16Assert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Wednesday));//17Assert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Thursday));//18Assert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Friday));//19Assert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Saturday));//20Assert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Sunday));//21Assert.AreEqual(start.AddDays(1), date.GetNextDate(DayOfWeek.Monday));//22//testing same month - include dateAssert.AreEqual(start = date, date.GetNextDate(DayOfWeek.Monday,false));//15Assert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Tuesday,false));//16Assert.AreEqual(start.AddDays(1), date.GetNextDate(DayOfWeek.Wednesday,false));//17//testing month change - forwardOnly
date =newDateTime(2013,7,29);
start = date;Assert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Tuesday));//30Assert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Wednesday));//31Assert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Thursday));//2013/09/01-month increasedAssert.AreEqual(start.AddDays(1), date.GetNextDate(DayOfWeek.Friday));//02//testing year change
date =newDateTime(2013,12,30);
start = date;Assert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Tuesday));//31Assert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Wednesday));//2014/01/01 - year increasedAssert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Thursday));//02}
Po obszernych testach wprowadziłem dodatkowe zmiany w stosunku do oryginalnej odpowiedzi. To teraz bezpiecznie obliczy następny dzień na podstawie użytej daty, przeszłości, teraźniejszości i przyszłości. Wszystkie poprzednie przykłady były świetne, ale zawiodły w pewnych warunkach. Nie uczyniłem tego stwierdzeniem jednowierszowym, aby można było poczynić dodatkowe uwagi na temat tego, co robią obliczenia. Pozytywny przypadek Jona Skeeta był świetny, chociaż przypadek, który miałem, to przesunięcie się o 1 dzień wstecz od daty, ale wciąż większe niż dzisiaj, a co, jeśli przeniesie się na dziś lub na wczoraj ... to rozwiązało problem.
AJB
1
Może to być również rozszerzenie, wszystko zależy
publicstaticclassDateTimeExtensions{publicstaticIEnumerable<DateTime>Next(thisDateTime date,DayOfWeek day){// This loop feels expensive and useless, but the point is IEnumerablewhile(true){if(date.DayOfWeek== day){yieldreturn date;}
date = date.AddDays(1);}}}
Stosowanie
var today =DateTime.Today;foreach(var monday in today.Next(DayOfWeek.Monday)){Console.WriteLine(monday);Console.ReadKey();}
Odpowiedzi:
Jak wspomniałem w komentarzach, jest wiele rzeczy, które możesz rozumieć przez „następny wtorek”, ale ten kod podaje „następny wtorek, który ma nastąpić lub dzisiaj, jeśli jest już wtorek”:
Jeśli chcesz podać „tydzień czasu”, jeśli jest już wtorek, możesz użyć:
... lub możesz użyć oryginalnej formuły, ale od jutra:
EDYCJA: Po prostu, aby to było ładne i wszechstronne:
Aby uzyskać wartość dla „dzisiaj lub w ciągu najbliższych 6 dni”:
Aby uzyskać wartość dla „następnego wtorku z wyłączeniem dzisiaj”:
źródło
+7)%7
Rozwiązanie jest całkiem ładna. Chociaż powodem, dla którego go nie użyłem, jest to, że jest to trochę mikro-optymalizacja i zbyt łatwo się pomylić (a także poświęcić trochę czytelności), oczywiście imho.To powinno załatwić sprawę:
źródło
.AddDays(1)
z pierwszej linii, w ten sposób również się sprawdziDateTime.Now
.Istnieją mniej rozwlekłe i bardziej sprytne / eleganckie rozwiązania tego problemu, ale poniższa funkcja C # działa naprawdę dobrze w wielu sytuacjach.
źródło
źródło
@Jon Skeet dobra odpowiedź.
Za poprzedni dzień:
Dzięki!!
źródło
DayOfWeek
wartości w następujący sposób:int daysToSubtract = -(((int)dateTime.DayOfWeek - (int)day + 7) % 7);
źródło
Bardzo prosta próbka do uwzględnienia lub wykluczenia aktualnej daty, określasz datę i dzień tygodnia, który Cię interesuje.
niektóre przypadki testowe
źródło
Może to być również rozszerzenie, wszystko zależy
Stosowanie
źródło
Teraz w smaku oneliner - na wypadek, gdyby trzeba było przekazać go jako parametr do jakiegoś mechanizmu.
W tym konkretnym przypadku:
źródło
Wersja celu C:
źródło