Як я можу вказати останній час доби за допомогою DateTime


78

Я використовую System.DateTimeоб’єкт, щоб дозволити користувачеві вибрати діапазон дат. Користувач може вибрати дату (а не час) лише за допомогою стороннього календаря, тому мені потрібно буде автоматично вказати час доби, який він повинен використовувати (тобто: 00:00:00 або 23:59:59) після дати вибрано.

Як я можу вказати час після того, як дата вже зберігається як об’єкт DateTime засобом вибору календаря? Я міг би використовувати AddHours, AddMinutes, AddSecondsметоди, але вони відносно поточного часу, який не може бути 00:00:00.

startDateПотрібно буде мати час 00:00:00 і endDateє час 23:59:59 для обліку всього дня.


Останній час доби о 23:59: 59.999?
Eppz,

Що ви маєте на увазі під словом "останній час доби"?
Даніель А. Уайт

Наскільки точно він впорається (але насправді, секунди повинні бути в порядку)
Джо Філліпс,

@ d03boy: Що ви маєте на увазі "змінити час"? Ви маєте на увазі встановити годинник ПК на цей час?
Джон Б

Відповіді:


107

Якщо ви вже створили DateTimeоб’єкт і хочете замінити час на 23:59:59 PM для даної дати, тоді ви можете використовувати .Dateвластивість, щоб отримати дату з часом, встановленим на 00:00:00, а потім додати години, хвилин і секунд. Наприклад:

var dt = yourDateInstance.Date.AddHours(23).AddMinutes(59).AddSeconds(59);

Якщо під останнім часом ви маєте на увазі 23:59:59 вечора, то це також має спрацювати:

var dt = new DateTime(Now.Year, Now.Month, Now.Day, 23, 59, 59);

Справді. Ніщо не говорить про те, що вам потрібно використовувати Now.XXX для створення року, місяця, дня, години, хвилини чи секунди. Ви можете створити DateTime, який представляє будь-який даний екземпляр часу.
Томас Оуенс,

Що робити, якщо я не зовсім впевнений, що вже встановлено 00:00:00? Чи можу я безпосередньо встановити час, замість того, щоб бути відносним?
Джо Філліпс,

1
Так, властивість .Date повертає компонент дати з часом, встановленим на 00:00:00. Ось чому в коді написано: youDateInstance.Date перед додаванням годин.
Хосе Базіліо

Дуже добре! Дякую за пояснення. Можливо, ви захочете додати це до своєї відповіді для нас, новачок, які можуть цього не помітити.
Джо Філліпс,

13
Технічно "найостанніший час доби" також містив би максимальну кількість галочок. Виконання найшвидшої відповіді: DateTime.Today.AddDays (1) .AddTicks (-1);
Пітер Дрір

83

Щоб отримати останню мить на сьогодні:

DateTime d = new DateTime(Now.Year, Now.Month, Now.Day);
d = d.AddDays(1);
d = d.AddTicks(-1);

У відповідь на ваше редагування ось що я б зробив:

DateTime start = new DateTime(Now.Year, Now.Month, Now.Day);
DateTime end = start.AddDays(1).AddTicks(-1);

// Or - just use end = start.AddDays(1), and use a < for comparison

+1. Я думав про те саме. У всіх вас є якась спеціальна клавіатура з вбудованим SO-intellisense / автозаповненням?
Еріх Мірабаль,

Тоді AddDays (1) встановить значення 00:00:00 наступного дня?
Джо Філліпс,

@ d03boy: точно. AddDays () буде рівно через 24 години. У цьому випадку о 00: 00: 00.0. Якщо ви хочете, щоб мить до цього, відніміть один галочку.
Джон Б

2
Це припускає, що для часу вже встановлено 00:00:00, що, можливо, тут не є безпечним припущенням. Чи можете ви якось прямо встановити час?
Джо Філліпс,

1
@ d03boy Jon B створив DateTime, вказавши рік, місяць і день. Це встановлює час на 0, тому в цьому випадку не потрібно додавати .Date перед додаванням дня.
Meta-Knight


13

На ваше запитання вже відповіли, але кращий спосіб IMHO - це не турбуватися, намагаючись відняти галочку, секунду або інше з кінця діапазону, а порівняти, використовуючи строго менше ніж.

Отже, якщо ви хочете, щоб усі дати були включеним діапазоном від startDate до endDate, ігноруючи час, ви можете використовувати наступне в C #:

if ((myDate >= startDate.Date) && (myDate < endDate.Date.AddDays(1)))
{
    // ... it's in the range
}

або в T-SQL, припускаючи, що ваші @StartDate і @EndDate рівно опівночі, приблизно так:

WHERE SomeDate >= @StartDate AND SomeDate < DATEADD(d,1,@EndDate)

ОНОВЛЕННЯ

Оновлений приклад, щоб показати інклюзивний діапазон у відповідь на коментарі.


IMO, endDate все одно повинні бути включені в пошук. Що робити, якщо я вибрав 2 червня та 2 червня як дати початку та закінчення?
Джо Філліпс,

Тоді ви можете просто додати день до endDate і скористатися кодом Джо ;-)
Meta-Knight

6
DateTime startDate = DateTime.Today;
DateTime stopDate = startDate.AddDays(1).AddTicks(-1);

Як примітка, DateTime.Todayповертається (з MSDN)

System.DateTime встановлено на сьогоднішню дату, а компонент часу встановлений на 00:00:00.

Отже, як зазначають інші, додайте день, потім відніміть найменший квант часу (галочка), і ви отримаєте останній можливий час для поточного дня.

Звичайно, вам, можливо, доведеться подумати про TimeZones і такі, залежно від того, де працює код, а не де користувач. Час за UTC може бути непоганим, але це може відштовхнути вас від дня (в будь-який спосіб) залежно від того, де працює ваш код.


Радий, що ви думаєте про часові пояси. Про це подбали.
Джо Філліпс,

5

На основі інших відповідей я створив цей зручний метод розширення:

public static class DateTimeExtensions
{
    public static DateTime EndOfDay(this DateTime dateTime)
    {
        return dateTime.Date.AddDays(1).AddTicks(-1);
    }
}

2

Наприклад

DateTime.Now.Date.AddDays(1).AddSeconds(-1)

Або AddTicks/AddMilliseconds/AddMinutes... на основі точності, яка вам потрібна.


2

Чому не розширення ToDayEnd ()

/// <summary>
    /// Gets the value of the End of the day (23:59)
    /// </summary>
    /// <param name="target"></param>
    /// <returns></returns>
    public static DateTime ToDayEnd(this DateTime target)
    {
        return target.Date.AddDays(1).AddMilliseconds(-1);
    }

Але якщо ви дійсно мали б на увазі абсолютний кінець дня, тоді AddTicks (-1) - це відповідь.


У якій бібліотеці це?
Джо Філліпс,

О, погано .. це була одна з бібліотек, якими я користувався. Я продовжував користуватися ним так сильно, що думав, що це частина Sytem.DateTime :)
akd

Хе-хе. Думав, що це може бути так
Джо Філліпс

@JoePhillips ви можете сказати, що це метод розширення, 1 він статичний, 2 в аргументах, переданих у ключовому слові this.
Кен

@Ken Я згоден. Це не говорить мені, яку бібліотеку мені потрібно імпортувати, щоб використовувати її. Це може бути власна бібліотека, а може бути і в рамках .net
Джо Філліпс

2

Використання методу розширення

public static DateTime EndOfTheDay(this DateTime date)
{
    return new DateTime(date.Year, date.Month, date.Day).AddDays(1).AddTicks(-1);
}

Результат тут забезпечить вам найсвіжіший час, отримавши початок дня - додайте день, а потім відніміть один галочку. Інші методи додають години, хвилини та секунди, однак ці рішення в залежності від функцій коду можуть викликати проблеми в будь-який час між 23: 59: 59.000000 та 23: 59: 59.999999

Наприклад, якщо я хочу знати, чи перебуває значення до певної дати / часу закінчення, з іншими рішеннями можливо, що вони будуть пропускати значення в діапазоні мілісекунд.


Дуже чисте, багаторазове рішення. Microsoft має чудову документацію щодо впровадження методів розширення тут .
Smitty-Werben-Jager-Manjenson



0

це дасть вам очікуваний результат:

DateTime startDate= DateTime.Now.Date;
DateTime endDate= startDate.AddDays(2).Add(new TimeSpan(23, 59, 59));
//startDate: 28/9/2017 0:0:0 endDate: 29/9/2017 23:59:59

1
Хоча ваш код працює, це може спричинити проблеми - а саме кінець дня - це не 23:59:59, якщо ваша значимість не в секундах. Якщо, однак, це те, в чому дані DateTime можуть зберігатися як (мілісекунди), найкраще включати мілісекунди як значуще значення. DateTime також зберігається в пам'яті як мілісекундне значення. [мілісекунди з 1 січня 1970 р.].
Кен

@Ken DateTime зберігається в кліщах (насправді лише в кліщах).
Джон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.