Тесты начала перехода на летнее время не выполняются для «стандартного времени GTB» в Windows - PullRequest
0 голосов
/ 05 ноября 2018

Я написал несколько тестов для преобразования времени из определенного часового пояса в UTC.

Правила гласят, что в Европе часы сдвинуты вперед в 01:00 UTC, для «стандартного времени GTB» это означает +2 UTC, например, 03:00:00.

Однако я обнаружил, что существуют расхождения в тестах для разных платформ (Linux против Windows) с использованием метода TimeZoneInfo.IsDaylightSavingTime (dateTime).

Я создал новый тестовый объект для даты и времени перехода DST:

var testDate = new DateTime(2019, 03, 31, 03, 20, 00); //20 minutes after Daylight Saving Time start
...

И передал его для объекта TimeZoneInfo 'timeZone', где часовой пояс был установлен на 'Стандартное время GTB':

...
    var timeZone = TimeZoneInfo.FindSystemTimeZoneById("GTB Standard Time");
    return timeZone.IsDaylightSavingTime(testDate);
}

Возвращает Ложь , хотя в 03:20:00 локально в 2019-03-31 летнее время уже должно быть включено. Это должно было вернуть True.

Мне удалось повторить этот тест только в Windows, используя встроенную базу данных для часовых поясов .Net. С помощью tzdata db (например, NodaTime ) возвращает True для этого теста.

Запутанная часть была в том, что Я вручную выдал ошибку для объекта timeZone, чтобы посмотреть, какая дополнительная информация поступает от объекта TimeZoneInfo, и обнаружил, что запуск DST действительно корректен:

timeZone.GetAdjustmentRules().First().DaylightTransitionStart.TimeOfDay

возвращает 03: 00: 00

Может ли кто-нибудь это подтвердить, а также есть ли способ проверить, где окна принимают время перехода на летнее время? Могу ли я выполнить текущий тестовый тест для Windows и Linux без использования каких-либо внешних библиотек?

1 Ответ

0 голосов
/ 05 ноября 2018

Местное время для этого часового пояса изменяется с 02:59:59 до 04:00:00 в этот конкретный день, поэтому 3:20:00 недопустимо. Он попадает в пропасть, созданную прямым переходом.

За документы для TimeZoneInfo.IsDaylightSavingTime(DateTime) (выделено мое)

Если параметр dateTime указывает недопустимое время, вызов метода создает исключение ArgumentException, если значением свойства Kind параметра dateTime является DateTimeKind.Local; в противном случае метод возвращает false.

Если можете, используйте вместо этого DateTimeOffset типы или DateTime с DateTimeKind.Utc. С любым из них нет никакой возможности неправильного или неоднозначного местного времени.

Если вы не можете этого сделать, то проверьте входные значения, используя IsInvalidTime и IsAmbiguousTime на объекте TimeZoneInfo, и вы можете принять решение в своем коде о том, как вы хотите обрабатывать результаты. Например, вы можете переместить 3:20 в 4:20 для этого экземпляра.

В случае неоднозначного времени, имейте в виду, что все методы в TimeZoneInfo (IsDaylightSavingTime, GetUtcOffset и т. Д.) По умолчанию принимают стандартное время , которое идет вторым последовательно. В этих сценариях почти всегда хочется летнего времени. Вы можете получить два доступных смещения, позвонив по номеру GetAmbiguousTimeOffsets и выбрав большее.

Также вы упомянули Noda Time - намного лучший API, ИМХО. Там такие вещи обрабатываются "resolvers". По умолчанию используется "lenient" resolver, если вы вызываете LocalDateTime.InZoneLeniently. Есть и другие распознаватели, и вы можете указать свои. Смотрите документы начиная с здесь .

...