TimeZoneInfo.GetAdjustmentRules
возвращает массив из AdjustmentRule
объектов, каждый из которых определяет корректировки времени, сделанные для перехода на летнее время. Это включает в себя дату начала и окончания, а также количество времени, в течение которого часы корректируются, и когда эти правила go вступают в силу (правила меняются, например, в США был цикл апрель-октябрь, а теперь его март-ноябрь) . Правила: обычно отсортированы от самого старого к самому новому.
Рассматриваемый код неверен (см. Ниже), находит последнее правило в списке (local.GetAdjustmentRules()[local.GetAdjustmentRules().Length - 1]
) и вычисляет, сколько время изменяется этим правилом (DaylightDelta
- в США это обычно один час, но в некоторых частях света могут быть установлены другие значения, например 30 минут)
Второй бит кода, о котором вы спрашиваете пытается нормализовать прошедшее время, если в одной / обеих зонах в настоящее время соблюдается летнее время. Это достигается путем добавления различий между двумя DaylightDelta
(количество часов, сдвинутых вперед / назад) и двумя BaseUtcOffset
(разница зоны без летнего времени и UT C). Затем он добавляет это время к исходному времени и вместо этого использует его для сравнения.
Код неверен по нескольким причинам (и это, возможно, не является исчерпывающим):
Это предполагает, что правила настройки упорядочены. В документации MSDN говорится, что они «обычно заказываются», но не дает никаких гарантий
Предполагается, что последнее правило корректировки является текущим. Как отмечалось выше, они не заказываются. Но они также могут содержать будущие правила, которые еще не вступили в силу
Это не учитывает время, близкое к полуночи, и может быть перенесено на следующий день. Это верно для обеих ветвей кода. Хотя открытие магазина после полуночи маловероятно, но вполне вероятно (я не знаю ваших бизнес-правил). Если магазин открыт с 8:00 до 2:00, тесты не пройдут в течение 1:00, когда он должен быть успешным
Аналогично, для магазина, где часы проходят до полуночи, расчет летнего времени может оказаться даже более неточно, если время попадает в границы перехода на летнее время.
TimeZoneInfo.Local
можно изменить с помощью системных настроек. Фактически, в зависимости от того, отмечен ли на панели управления «Автоматически переходить на летнее время», информация о местном часовом поясе всегда может возвращать false
для IsDaylightSavings
и массив нулевой длины для local.GetAdjustmentRules
. Это означает, что один и тот же код, запущенный на двух компьютерах, может возвращать разные результаты, даже если они находятся рядом друг с другом!
Предполагается, что система обновлена. В зависимости от того, где вы находитесь, правила перехода на летнее время могут часто меняться. В подобных случаях операционная система, как правило, не содержит всей последней информации.
Работа с часовыми поясами и переходом на летнее время является сложной задачей. Правила все время меняются, а инструменты во фреймворке довольно неуклюжи, и с ними сложно работать (если вы их понимаете). Что еще хуже, они не всегда обновляются!
Я не собираюсь пытаться предоставить вам фиксированный код. Я предпочитаю оставлять все, что связано со временем и расчетами летнего времени, экспертам. Я настоятельно рекомендую заглянуть в библиотеку NodaTime для подобных вычислений. Он полностью посвящен теме, а правила часовых поясов регулярно обновляются. На их странице Почему мы существуем упоминаются некоторые из вещей, которые я упомянул выше, как и это сообщение в блоге , написанное одним из авторов библиотеки, Джоном Скитом.