CTimeSpan.GetDays () и переход на летнее время
Вопрос
Я обнаружил ошибку в старой программе C ++ MFC, которая вычисляет смещение (в днях) для заданной даты от фиксированной базовой даты. Мы увидели результаты, которые по какой-то причине были единичными, и я отследил их там, где первоначальный программист использовал метод CTimeSpan.GetDays (). Согласно документации :
Обратите внимание, что переход на летнее время может привести к тому, что GetDays выдаст потенциально неожиданный результат. Например, когда действует летнее время, GetDays сообщает количество дней между 1 апреля и 1 мая как 29, а не 30, поскольку один день в апреле сокращается на час и, следовательно, не считается полным днем.
Мое предлагаемое исправление - использовать (obj.GetTotalHours () + 1) / 24
. Я думаю, что это покроет все проблемы, так как это пакетная работа, которая выполняется примерно в одно и то же время каждый день, но я подумал, что перед тем, как ее реализовать, я бы попросил умных людей, если это возможно, найти лучший способ. Р>
Это всего лишь побочный вопрос, но мне также любопытно, как это можно было бы решить, если бы программа могла быть запущена в любое время.
Решение
Ваше исправление отлично работает, чтобы получить количество целых 24-часовых периодов между двумя периодами, если события происходят в одно и то же время каждый день. В противном случае это "+ 1" в выражении может привести к ошибке off-by-one.
Иногда вас не волнует, в какое время дня произошло событие, вы просто хотите знать, в какой день. В этом случае вам нужно обнулить часы, минуты и секунды, а затем использовать формулу:
CTime startDay(start.GetYear(), start.GetMonth(), start.GetDay(), 0, 0, 0);
CTime finishDay(finish.GetYear(), finish.GetMonth(), finish.GetDay(), 0, 0, 0);
int days = ((finishDay - startDay).GetTotalHours() + 1) / 24;
Другие советы
Незначительное изменение предложенного Марком, и оно работает без использования округления: просто добавьте еще один нулевой параметр в конструктор CTime
. Это заставляет оба раза быть в стандартное время (не летнее время). Значением по умолчанию для этого параметра является -1, что означает «Автоматически вычислять, если действует летнее время».
// Discard hours, minutes, seconds, and daylight savings time
CTime startDay(start.GetYear(), start.GetMonth(), start.GetDay(), 0, 0, 0, 0);
CTime endDay(end.GetYear(), end.GetMonth(), end.GetDay(), 0, 0, 0, 0);
// Get number of days apart
CTimeSpan span = endDay - startDay;
int nDays = span.GetDays();
Протестировано и работает.