Я хочу получить первый и последний день месяца, в котором находится заданная дата. Дата берется из значения в поле пользовательского интерфейса.
Если я использую средство выбора времени, я могу сказать
var maxDay = dtpAttendance.MaxDate.Day;
Но я пытаюсь получить его из объекта DateTime. Итак, если у меня есть это ...
DateTime dt = DateTime.today;
Как получить первый день и последний день месяца с dt
?
_Date
переменной хранится одно значение . Какие «минимальные и максимальные значения» вы пытаетесь получить из этого значения?Ответы:
DateTime
структура хранит только одно значение, а не диапазон значений.MinValue
иMaxValue
являются статическими полями, которые содержат диапазон возможных значений для экземпляровDateTime
структуры. Эти поля статичны и не относятся к конкретному экземпляруDateTime
. Они относятся кDateTime
самому типу.Рекомендуемая литература: статические (Справочник по C #)
ОБНОВЛЕНИЕ: получение диапазона месяцев:
DateTime date = ... var firstDayOfMonth = new DateTime(date.Year, date.Month, 1); var lastDayOfMonth = firstDayOfMonth.AddMonths(1).AddDays(-1);
источник
lastDayofMonth
бытьfirstDayOfMonth.AddMonths(1).AddSeconds(-1);
?AddTicks(-1)
, но если мы не будем заботиться о части времени и думать только о части даты, тогда дни работают нормально< firstDayOfNextMonth
вместо<= lastDayOfMonth
. Таким образом, он всегда будет работать независимо от степени детализации. (Я уверен, с клещами все будет в порядке, но кто знает, что принесет будущее ... нанотики?)Это более длинный комментарий к ответам @Sergey и @ Steffen. Написав подобный код в прошлом, я решил проверить, какой из них наиболее эффективен , помня, что ясность тоже важна.
Результат
Вот пример результата тестового запуска для 10 миллионов итераций:
Код
Я использовал LINQPad 4 (в режиме программы C #) для запуска тестов с включенной оптимизацией компилятора. Вот проверенный код, размеченный как методы расширения для ясности и удобства:
public static class DateTimeDayOfMonthExtensions { public static DateTime FirstDayOfMonth_AddMethod(this DateTime value) { return value.Date.AddDays(1 - value.Day); } public static DateTime FirstDayOfMonth_NewMethod(this DateTime value) { return new DateTime(value.Year, value.Month, 1); } public static DateTime LastDayOfMonth_AddMethod(this DateTime value) { return value.FirstDayOfMonth_AddMethod().AddMonths(1).AddDays(-1); } public static DateTime LastDayOfMonth_AddMethodWithDaysInMonth(this DateTime value) { return value.Date.AddDays(DateTime.DaysInMonth(value.Year, value.Month) - value.Day); } public static DateTime LastDayOfMonth_SpecialCase(this DateTime value) { return value.AddDays(DateTime.DaysInMonth(value.Year, value.Month) - 1); } public static int DaysInMonth(this DateTime value) { return DateTime.DaysInMonth(value.Year, value.Month); } public static DateTime LastDayOfMonth_NewMethod(this DateTime value) { return new DateTime(value.Year, value.Month, DateTime.DaysInMonth(value.Year, value.Month)); } public static DateTime LastDayOfMonth_NewMethodWithReuseOfExtMethod(this DateTime value) { return new DateTime(value.Year, value.Month, value.DaysInMonth()); } } void Main() { Random rnd = new Random(); DateTime[] sampleData = new DateTime[10000000]; for(int i = 0; i < sampleData.Length; i++) { sampleData[i] = new DateTime(1970, 1, 1).AddDays(rnd.Next(0, 365 * 50)); } GC.Collect(); System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew(); for(int i = 0; i < sampleData.Length; i++) { DateTime test = sampleData[i].FirstDayOfMonth_AddMethod(); } string.Format("{0} ms for FirstDayOfMonth_AddMethod()", sw.ElapsedMilliseconds).Dump(); GC.Collect(); sw.Restart(); for(int i = 0; i < sampleData.Length; i++) { DateTime test = sampleData[i].FirstDayOfMonth_NewMethod(); } string.Format("{0} ms for FirstDayOfMonth_NewMethod()", sw.ElapsedMilliseconds).Dump(); GC.Collect(); sw.Restart(); for(int i = 0; i < sampleData.Length; i++) { DateTime test = sampleData[i].LastDayOfMonth_AddMethod(); } string.Format("{0} ms for LastDayOfMonth_AddMethod()", sw.ElapsedMilliseconds).Dump(); GC.Collect(); sw.Restart(); for(int i = 0; i < sampleData.Length; i++) { DateTime test = sampleData[i].LastDayOfMonth_AddMethodWithDaysInMonth(); } string.Format("{0} ms for LastDayOfMonth_AddMethodWithDaysInMonth()", sw.ElapsedMilliseconds).Dump(); GC.Collect(); sw.Restart(); for(int i = 0; i < sampleData.Length; i++) { DateTime test = sampleData[i].LastDayOfMonth_NewMethod(); } string.Format("{0} ms for LastDayOfMonth_NewMethod()", sw.ElapsedMilliseconds).Dump(); GC.Collect(); sw.Restart(); for(int i = 0; i < sampleData.Length; i++) { DateTime test = sampleData[i].LastDayOfMonth_NewMethodWithReuseOfExtMethod(); } string.Format("{0} ms for LastDayOfMonth_NewMethodWithReuseOfExtMethod()", sw.ElapsedMilliseconds).Dump(); for(int i = 0; i < sampleData.Length; i++) { sampleData[i] = sampleData[i].FirstDayOfMonth_AddMethod(); } GC.Collect(); sw.Restart(); for(int i = 0; i < sampleData.Length; i++) { DateTime test = sampleData[i].LastDayOfMonth_SpecialCase(); } string.Format("{0} ms for LastDayOfMonth_SpecialCase()", sw.ElapsedMilliseconds).Dump(); }
Анализ
Некоторые из этих результатов меня удивили.
Хотя в нем не так много всего, он
FirstDayOfMonth_AddMethod
был немного быстрее, чемFirstDayOfMonth_NewMethod
в большинстве прогонов теста. Однако я думаю, что последний имеет несколько более ясное намерение, и поэтому я предпочитаю это.LastDayOfMonth_AddMethod
был явным проигравшим противLastDayOfMonth_AddMethodWithDaysInMonth
,LastDayOfMonth_NewMethod
иLastDayOfMonth_NewMethodWithReuseOfExtMethod
. Между самой быстрой тройкой нет ничего особенного, поэтому все зависит от ваших личных предпочтений. Я выбираю ясностьLastDayOfMonth_NewMethodWithReuseOfExtMethod
с повторным использованием другого полезного метода расширения. IMHO его намерение более ясное, и я готов принять небольшую стоимость производительности.LastDayOfMonth_SpecialCase
предполагает, что вы указываете первое число месяца в особом случае, когда вы, возможно, уже вычислили эту дату, иDateTime.DaysInMonth
для получения результата использует метод add with . Это быстрее, чем другие версии, как и следовало ожидать, но если вы не остро нуждаетесь в скорости, я не вижу смысла иметь этот особый случай в вашем арсенале.Вывод
Вот класс метода расширения с моим выбором и в целом согласен с @Steffen, я считаю:
public static class DateTimeDayOfMonthExtensions { public static DateTime FirstDayOfMonth(this DateTime value) { return new DateTime(value.Year, value.Month, 1); } public static int DaysInMonth(this DateTime value) { return DateTime.DaysInMonth(value.Year, value.Month); } public static DateTime LastDayOfMonth(this DateTime value) { return new DateTime(value.Year, value.Month, value.DaysInMonth()); } }
Если вы зашли так далеко, спасибо за потраченное время! Было весело: ¬). Прокомментируйте, если у вас есть другие предложения по этим алгоритмам.
источник
LastDayOfMonth_AddMethod_SpecialCase
(или что-то в этом роде). Ожидая первого дня месяца в качестве параметра, я думаю, что самое быстрое должно быть то, чтоLastDayOfMonth_AddMethod
происходит! Это будет очень просто:return value.AddMonths(1).AddDays(-1);
Получение диапазона месяцев с .Net API (просто другой способ):
DateTime date = ... var firstDayOfMonth = new DateTime(date.Year, date.Month, 1); var lastDayOfMonth = new DateTime(date.Year, date.Month, DateTime.DaysInMonth(date.Year, date.Month));
источник
"
Last day of month
" на самом деле "First day of *next* month, minus 1
". Итак, вот что я использую, метод "DaysInMonth" не нужен:public static DateTime FirstDayOfMonth(this DateTime value) { return new DateTime(value.Year, value.Month, 1); } public static DateTime LastDayOfMonth(this DateTime value) { return value.FirstDayOfMonth() .AddMonths(1) .AddMinutes(-1); }
ПРИМЕЧАНИЕ. Причина, по которой я использую
AddMinutes(-1)
, а неAddDays(-1)
здесь, заключается в том, что обычно вам нужны эти функции даты для отчетности за какой-то период, и когда вы создаете отчет за период, "дата окончания" должна быть примерно такой,Oct 31 2015 23:59:59
чтобы ваш отчет работал правильно - включая все данные за последний день месяца.Т.е. вы действительно получаете здесь «последний момент месяца». Не последний день.
Хорошо, я сейчас заткнусь.
источник
DateTime dCalcDate = DateTime.Now; dtpFromEffDate.Value = new DateTime(dCalcDate.Year, dCalcDate.Month, 1); dptToEffDate.Value = new DateTime(dCalcDate.Year, dCalcDate.Month, DateTime.DaysInMonth(dCalcDate.Year, dCalcDate.Month));
источник
description
которое помогает объяснить ваш код. СпасибоЗдесь вы можете добавить один месяц к первому дню текущего месяца, чем удалить 1 день с этого дня.
DateTime now = DateTime.Now; var startDate = new DateTime(now.Year, now.Month, 1); var endDate = startDate.AddMonths(1).AddDays(-1);
источник
Если тебя волнует только дата
var firstDay = new DateTime(date.Year, date.Month, 1, 0, 0, 0, date.Kind); var lastDay = new DateTime(date.Year, date.Month, 1, 0, 0, 0, date.Kind).AddMonths(1).AddDays(-1);
Если хочешь сберечь время
var firstDay = new DateTime(date.Year, date.Month, 1, date.Hour, date.Minute, date.Second, date.Kind); var lastDay = new DateTime(date.Year, date.Month, 1, date.Hour, date.Minute, date.Second, date.Kind).AddMonths(1).AddDays(-1);
источник
В принятом здесь ответе не учитывается тип экземпляра DateTime. Например, если ваш исходный экземпляр DateTime был типом UTC, то, создав новый экземпляр DateTime, вы создадите экземпляр Unknown Kind, который затем будет обрабатываться как местное время на основе настроек сервера. Поэтому более правильный способ получить первую и последнюю дату месяца будет следующим:
var now = DateTime.UtcNow; var first = now.Date.AddDays(-(now.Date.Day - 1)); var last = first.AddMonths(1).AddTicks(-1);
Таким образом сохраняется исходный вид экземпляра DateTime.
источник
Попробуй это:
string strDate = DateTime.Now.ToString("MM/01/yyyy");
источник
Я использовал это в своем сценарии (работает для меня), но мне нужна была полная дата без необходимости обрезать ее только до даты и без времени.
public DateTime GetLastDayOfTheMonth() { int daysFromNow = DateTime.DaysInMonth(DateTime.Now.Year, DateTime.Now.Month) - (int)DateTime.Now.Day; return DateTime.Now.AddDays(daysFromNow); }
источник
Для персидской культуры
PersianCalendar pc = new PersianCalendar(); var today = pc.GetDayOfMonth(DateTime.Now); var firstDayOfMonth = pc.GetDayOfMonth(DateTime.Now.AddDays(-(today-1))); var lastDayOfMonth = pc.GetDayOfMonth(DateTime.Now.AddMonths(1).AddDays(-today)); Console.WriteLine("First day "+ firstDayOfMonth); Console.WriteLine("Last day " + lastDayOfMonth);
источник
Попробуйте. Он в основном вычисляет количество прошедших дней
DateTime.Now
, затем вычитает из него единицу и использует новое значение, чтобы найти первое число текущего месяца. Оттуда он использует этоDateTime
и использует.AddMonths(-1)
для получения первых чисел предыдущего месяца.Получение последнего дня прошлого месяца делает в основном то же самое, за исключением того, что добавляет единицу к количеству дней в месяце и вычитает это значение из
DateTime.Now.AddDays
, давая вам последний день предыдущего месяца.int NumberofDays = DateTime.Now.Day; int FirstDay = NumberofDays - 1; int LastDay = NumberofDays + 1; DateTime FirstofThisMonth = DateTime.Now.AddDays(-FirstDay); DateTime LastDayOfLastMonth = DateTime.Now.AddDays(-LastDay); DateTime CheckLastMonth = FirstofThisMonth.AddMonths(-1);
источник
Ты можешь это сделать
DateTime dt = DateTime.Now; DateTime firstDayOfMonth = new DateTime(dt.Year, date.Month, 1); DateTime lastDayOfMonth = firstDayOfMonth.AddMonths(1).AddDays(-1);
источник
простой способ сделать это
Begin = new DateTime(DateTime.Now.Year, DateTime.Now.Month,1).ToShortDateString(); End = new DataFim.Text = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.DaysInMonth(DateTime.Now.Year, DateTime.Now.Month)).ToShortDateString();
источник
DateTime dCalcDate = DateTime.Now; var startDate = new DateTime(Convert.ToInt32(Year), Convert.ToInt32(Month), 1); var endDate = new DateTime(Convert.ToInt32(Year), Convert.ToInt32(Month), DateTime.DaysInMonth((Convert.ToInt32(Year)), Convert.ToInt32(Month)));
источник