Почему TimeZoneInfo.IsValidTime () дает неожиданный результат для DateTimeKind.Local? - PullRequest
2 голосов
/ 03 мая 2020

Меня удивляет поведение TimeZoneInfo.IsValidTime (), поскольку оно не работает, как я ожидал, с недопустимым DateTime, установленным в качестве DateTimeKind.Local

[Fact]
public void DateTimeInvalidForTimeZone()
{
    TimeZoneInfo timeZone = TimeZoneInfo.FindSystemTimeZoneById("Central European Standard Time");

    var testTimeUnspec = new DateTime(2020, 3, 29, 02, 01, 0, DateTimeKind.Unspecified);
    var testTimeLocal = new DateTime(2020, 3, 29, 02, 01, 0, DateTimeKind.Local);
    var testTimeUtc = new DateTime(2020, 3, 29, 02, 01, 0, DateTimeKind.Utc);

    Assert.False(timeZone.IsInvalidTime(testTimeUtc));     //as anticipated - UTC so cannot be invalid
    Assert.True(timeZone.IsInvalidTime(testTimeUnspec));   //as anticipated - the time is invalid
    Assert.False(timeZone.IsInvalidTime(testTimeLocal));   //unexpected - the time is invalid
}

Примечание. Центральноевропейское стандартное время переходит в переход на летнее время 29 марта 2020 года в 02:00, поэтому временная последовательность по местному времени составляет 01:59:58, 01:59:59, 03:00:00, 03:00:01. Соответственно, все локальные времена между 02:00:00 и 02:59:59 являются недействительными.

Документация Microsoft объясняет:

  • В случае DateTimeKind.Local и TimeZoneInfo, которые не являются локальными (т.е. отличаются от часового пояса компьютера) IsValidTime (DateTime) преобразует DateTime во время объекта TimeZoneInfo и возвращает false.

Это говорит о том, что объекты DateTime, которые являются DateTimeKind.Local, всегда будут действительными, что не то, что я ожидаю или хочу. Кто-нибудь может объяснить логику c за реализацией Microsoft? Еще одна причина рассмотреть Nodatime?

1 Ответ

1 голос
/ 04 мая 2020

Как вы указали, документы для TimeZoneInfo.IsInvalidTime объясняют, что возвращение false является документированным поведением, когда TimeZoneInfo не является местным часовым поясом и является правильным независимо от того, является ли время действителен либо в местном часовом поясе, либо в зоне TimeZoneInfo. Действительно, реализация просто возвращает false в этом случае.

Если вы хотите знать, действительны ли локальные времена или нет, вам нужно использовать часовой пояс TimeZoneInfo.Local, а не тот, который получен по id. Не имеет значения, является ли указанный часовой пояс локальным или нет, вам нужно явно работать с TimeZoneInfo.Local, если вы проверяете DateTimeKind.Local значений.

Другими словами, если * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} * * * * * * * * * * * * * то * * * * * * * * * * * * *.

...