Подтвердить что ты не робот

Как узнать время начала и окончания дня

В моем приложении на С# я передаю строковую переменную в формате yyyymmdd-yyyymmdd, представляющую дату и дату. Я хочу получить время начала и окончания этих дат соответственно. В настоящее время у меня есть код ниже, но мне было интересно, есть ли более элегантное решение?

Таким образом, для pdr = 20090521-20090523 будет получено "20090521 00:00:00" и "20090523 23:59:59"

private void ValidateDatePeriod(string pdr, out DateTime startDate, 
                                out DateTime endDate)
{
    string[] dates = pdr.Split('-');

    if (dates.Length != 2)
    {
        throw new Exception("Date period is of incorrect format");
    }

    if (dates[0].Length != 8 || dates[1].Length != 8)
    {
        throw new Exception("Split date periods are of incorrect format");
    }

    startDate = DateTime.ParseExact(dates[0] + " 00:00:00", 
        "yyyyMMdd HH:mm:ss", null);
    endDate = DateTime.ParseExact(dates[1] + "23:59:59", 
        "yyyyMMdd HH::mm:ss", null);
}
4b9b3361

Ответ 1

Если вас беспокоит только точность .Net...

startDate = DateTime.ParseExact(dates[0], "yyyyMMdd");
endDate = DateTime.ParseExact(dates[1], "yyyyMMdd").AddTicks(-1).AddDays(1);

Вам действительно не нужно конкатенировать дополнительные значения в строке для временной части.


В качестве дополнения, если вы используете это для запроса против, например, базы данных...

startDate = DateTime.ParseExact(dates[0], "yyyyMMdd");
endDate = DateTime.ParseExact(dates[1], "yyyyMMdd").AddDays(1);

С запросом...

WHERE "startDate" >= @startDate AND "endDate" < @endDate

Тогда вопросы точности, отмеченные в комментариях, не будут иметь большого значения. endDate в этом случае не будет частью диапазона, а внешней границей.

Ответ 2

Я удивлен, увидев, как неправильный ответ получил так много upvotes:

Wrong value

Правильная версия будет следующей:

public static DateTime StartOfDay(this DateTime theDate)
{
    return theDate.Date;
}

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

Ответ 3

Вы можете определить два метода расширения где-нибудь в классе утилиты:

public static DateTime EndOfDay(this DateTime date)
{
    return new DateTime(date.Year, date.Month, date.Day, 23, 59, 59, 999);
}

public static DateTime StartOfDay(this DateTime date)
{
    return new DateTime(date.Year, date.Month, date.Day, 0, 0, 0, 0);
}

И затем используйте их в коде так:

public DoSomething()
{
    DateTime endOfThisDay = DateTime.Now.EndOfDay();
}

Ответ 4

Объект DateTime имеет свойство Date, которое возвращает только часть даты. (Временная часть по умолчанию установлена ​​до 12:00 утра).

Я бы рекомендовал в качестве более элегантного решения (IMHO): если вы хотите разрешить какое-либо время в последний день, то вы добавляете 1 день к дате и сравниваете, чтобы время, большее или равное дате начала, но строго меньше даты окончания (плюс 1 день).

// Calling code.  beginDateTime and endDateTime are already set.
// beginDateTime and endDateTime are inclusive.
// targetDateTime is the date you want to check.
beginDateTime = beginDateTime.Date;
endDateTime = endDateTime.Date.AddDays(1);

if ( beginDateTime <= targetDateTime &&
     targetDateTime < endDateTime )
   // Do something.

Ответ 5

Это в значительной степени то, что я сделал бы, с некоторыми небольшими настройками (на самом деле неважно, просто nitpicking):

  • Следует использовать методы TryParse()/TryParseExact(), которые возвращают false вместо исключения исключений.
  • FormatException более конкретный, чем Exception
  • Не нужно проверять длину == 8, потому что ParseExact()/TryParseExact() сделает это
  • "00:00:00" и "23:59:59" не нужны
  • return true/false Вы можете проанализировать, вместо того, чтобы бросать исключение (не забудьте проверить значение, возвращаемое этим методом!)

код:

private bool ValidateDatePeriod(string pdr, out DateTime startDate, 
                        out DateTime endDate)
{
   string[] dates = pdr.Split('-');

   if (dates.Length != 2)
   {
       return false;
   }

   // no need to check for Length == 8 because the following will do it anyway
   // no need for "00:00:00" or "23:59:59" either, I prefer AddDays(1)

   if(!DateTime.TryParseExact(dates[0], "yyyyMMdd", null, DateTimeStyles.None, out startDate))
      return false;

   if(!DateTime.TryParseExact(dates[1], "yyyyMMdd", null, DateTimeStyles.None, out endDate))
      return false;

   endDate = endDate.AddDays(1);
   return true;
}

Ответ 6

Я думаю, что мы делаем это неправильно. Нет такой вещи, как конец дня. AddTick(-1) работает только по соглашению, что нет временных интервалов, меньших галочки. Это зависит от реализации. Разумеется, вопрос связан с эталонной реализацией, а именно с классом .Net Framework DateTime, но все же мы должны считать это ключом к тому, что функция, которую мы действительно хотим, это не EndOfDay(), а StartOfNextDay()

public static DateTime StartOfNextDay(this DateTime date)
{
    return date.Date.AddDays(1);
}

Ответ 7

Я использую следующее в С#

public static DateTime GetStartOfDay(DateTime dateTime)
{
    return new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 0, 0, 0, 0);
}
public static DateTime GetEndOfDay(DateTime dateTime)
{
    return new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 23, 59, 59, 999);
}

Затем в MS SQL я делаю следующее:

if datepart(ms, @dateEnd) = 0
   set @dateEnd = dateadd(ms, -3, @dateEnd)

Это приведет к времени MS SQL 23: 59: 59.997, которое является максимальным временем до того, как станет на следующий день.

Вы можете просто использовать:

new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 23, 59, 59, 999);

Что будет работать в MS SQL, но это не так точно на стороне .Net.

Ответ 8

Для SQL Server (версия 2008 R2 протестирована) эти диапазоны работают.

StarDate '2016-01-11 00: 00: 01.990' EndDate '2016-01-19 23: 59: 59.990'

Кажется, что тики больше, чем последняя секунда дня и автоматически округляются до следующего дня. Так что я тестирую и работаю, я создал фиктивную таблицу с двумя датами для проверки того, какие значения занимает sql-сервер, и вставляя в хранимую процедуру эти параметры.