ASP.NET - это набор веб-технологий. C # это язык. Вы действительно должны думать об этом с точки зрения простого .NET. Теперь для «следующего вторника» - это «первый вторник после сегодняшнего дня»? Если бы это был понедельник, и кто-то сказал бы «Увидимся в следующий вторник», я бы ожидал, что это будет означать 8 дней, а не 1. А что если сегодня вторник? Какое время суток вам нужно?
Джон Скит
Если сегодня вторник, вы хотите найти дату, когда следующий вторник? Или сегодня понедельник, вы хотите найти второй вторник с понедельника?
Пожарная панда
Ближайший вторник, ожидающий того или иного дня.
Brenjt
2
@brenjtL: а если уже вторник?
Джон Скит
Если уже вторник, то в тот же день
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);
Если вы хотите указать «неделю», если уже вторник, вы можете использовать:
// 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);
РЕДАКТИРОВАТЬ: Просто чтобы сделать это красиво и универсально:
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);}
Итак, чтобы получить значение для «сегодня или в ближайшие 6 дней»:
Ого, мне просто интересно, как я смогу получить n-е дни до следующего вторника, а вы тогда обновили свой ответ примером Nice. Спасибо
brenjt
Трудно было выбрать правильный ответ. Но ваш, кажется, самый универсальный, и вы сделали его легким для понимания. Спасибо за помощь.
Brenjt
1
@brenjt: На самом деле я бы сказал, что Sven's более универсален, так как вы можете указать день недели, но это ваш звонок :) (Теперь я отредактировал мой, чтобы дать более обобщенную версию.)
Jon Skeet
1
+7)%7Решение довольно приятно , хотя. Хотя причина, по которой я не использовал это, заключается в том, что это немного микрооптимизация и слишком легко ошибиться (а также пожертвовать некоторой читабельностью), imho конечно.
Свен
Модульный тест: [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
Это должно сделать трюк:
staticDateTimeGetNextWeekday(DayOfWeek day){DateTime result =DateTime.Now.AddDays(1);while( result.DayOfWeek!= day )
result = result.AddDays(1);return result;}
Отличный ответ, если сегодня вторник (а это ха), вернется ли это сегодня или в следующий вторник?
Brenjt
3
Это вернется в следующий вторник. Если вы хотите, чтобы он вернулся сегодня, просто удалите .AddDays(1)из первой строки, таким образом он также проверит DateTime.Nowсебя.
Свен
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>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);}
Единственный ответ, который реализуется как расширение DateTime. В то время как все другие решения работают, использование его в качестве метода расширения дает самый простой в использовании код.
Если сегодня понедельник, то ответ, который вы предоставили, даст неделю со вторника, а не завтра.
Тони
5
@ Джон Скит хороший ответ.
За предыдущий день:
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);}
Обратите внимание, что это решение включает отрицательные числа, передаваемые оператору по модулю. В статье в Википедии об операторе по модулю говорится, что «когда a или n отрицательны, наивное определение нарушается, и языки программирования различаются в том, как определяются эти значения». Хотя это, вероятно, работает в C #, математически более «солидным» решением для получения того же результата было бы поменять местами такие DayOfWeekзначения:int daysToSubtract = -(((int)dateTime.DayOfWeek - (int)day + 7) % 7);
Очень простой образец для включения или исключения текущей даты, вы указываете дату и день недели, в которую вы заинтересованы.
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);}}
некоторые тесты
[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}
Я внес дополнительные изменения по сравнению с первоначальным ответом после некоторого обширного тестирования. Теперь он будет безопасно рассчитывать следующий день на основе использованной даты, прошлого, настоящего и будущего. Все предыдущие примеры были великолепны, но провалились при определенных условиях. Я не сделал это однострочным заявлением, чтобы можно было сделать дополнительные комментарии к тому, что делают вычисления. Положительный пример Джона Скита был великолепен, хотя у меня был случай переместиться на 1 день назад от даты, но все же больше, чем сегодня, и что если он перейдет на сегодня или на вчера ... это решило это.
AJB
1
Это может быть также расширение, все зависит
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);}}}
использование
var today =DateTime.Today;foreach(var monday in today.Next(DayOfWeek.Monday)){Console.WriteLine(monday);Console.ReadKey();}
Ответы:
Как я уже упоминал в комментариях, есть несколько вещей, которые вы можете подразумевать под «следующим вторником», но этот код дает вам «наступить следующий вторник или сегодня, если уже вторник»:
Если вы хотите указать «неделю», если уже вторник, вы можете использовать:
... или вы можете использовать оригинальную формулу, но с завтрашнего дня:
РЕДАКТИРОВАТЬ: Просто чтобы сделать это красиво и универсально:
Итак, чтобы получить значение для «сегодня или в ближайшие 6 дней»:
Чтобы получить значение для «следующий вторник, исключая сегодня»:
источник
+7)%7
Решение довольно приятно , хотя. Хотя причина, по которой я не использовал это, заключается в том, что это немного микрооптимизация и слишком легко ошибиться (а также пожертвовать некоторой читабельностью), imho конечно.Это должно сделать трюк:
источник
.AddDays(1)
из первой строки, таким образом он также проверитDateTime.Now
себя.Существует менее многословное и более умное / элегантное решение этой проблемы, но следующая функция C # действительно хорошо работает для ряда ситуаций.
источник
источник
@ Джон Скит хороший ответ.
За предыдущий день:
Спасибо!!
источник
DayOfWeek
значения:int daysToSubtract = -(((int)dateTime.DayOfWeek - (int)day + 7) % 7);
источник
Очень простой образец для включения или исключения текущей даты, вы указываете дату и день недели, в которую вы заинтересованы.
некоторые тесты
источник
Это может быть также расширение, все зависит
использование
источник
Теперь во вкусе oneliner - в случае, если вам нужно передать его в качестве параметра в некоторый механизм.
В этом конкретном случае:
источник
Цель C Версия:
источник