DateTime.ToLocalTime () зимой / летом - PullRequest
8 голосов
/ 02 ноября 2011

Я использую DateTime.ToLocalTime() для преобразования дат из UTC в местное время. Мой часовой пояс GMT + 1 (Белград, Будапешт, Любина ...), он правильно установлен в Windows Settings (XP).

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

Как я вижу, метод ToLocalTime ведет себя странно с того момента. Когда я использую его для преобразования дат после зимнего времени, оно отлично работает, например:

var utcDate2 = new DateTime(2011, 11, 2, 9, 0, 0,DateTimeKind.Utc);

utcDate1.ToLocalTime() значение: 2011.11.02. 10:00:00 правильно

Беда, когда я хочу преобразовать дату до этого изменения (например, дату из летнего времени), она возвращает неверное значение, подобное этому:

var utcDate1 = new DateTime(2011, 10, 23, 9, 0, 0,DateTimeKind.Utc);

utcDate2.ToLocalTime() значение: 2011.10.23. 10:00:00 неверно Должно быть 2011.10.23. 11: 00: 00

Что я должен сделать, чтобы получить правильные значения? Как мне использовать ToLocalTime, который также регулирует зимнее / летнее время?

Ответы [ 4 ]

6 голосов
/ 02 ноября 2011

http://msdn.microsoft.com/en-us/library/system.datetime.tolocaltime.aspx

В системах Windows XP метод ToLocalTime распознает только текущее правило корректировки при конвертации из UTC в местное время. Как результат, преобразования за периоды до текущего правила корректировки вступивший в силу может не совсем точно отражать разницу между UTC и местное время.

Так что вам придется искать другой способ выяснить это.

1 голос
/ 02 ноября 2011

Я использую тот же часовой пояс, и когда я пытаюсь это сделать, я получаю правильные значения:

var utcDate1 = new DateTime(2011, 10, 23, 9, 0, 0, DateTimeKind.Utc);
Console.WriteLine(utcDate1);
Console.WriteLine(utcDate1.ToLocalTime());

var utcDate2 = new DateTime(2011, 11, 2, 9, 0, 0, DateTimeKind.Utc);
Console.WriteLine(utcDate2);
Console.WriteLine(utcDate2.ToLocalTime());

Выход:

2011-10-23 09:00:00
2011-10-23 11:00:00
2011-11-02 09:00:00
2011-11-02 10:00:00
1 голос
/ 02 ноября 2011

Я предполагаю, что данные часового пояса в вашей системе могут быть устаревшими - или это связано с упомянутым ограничением jsobo.

Один вариант, который вы могли бы хотеть (осторожно) использовать, использует мой API даты / времени, Время Noda . Это имеет преобразование в / из DateTime, так что вы могли бы использовать DateTime в другом месте вашего кода, хотя, очевидно, я считаю, что ваш код будет более понятным, если вы будете использовать Noda Time повсюду:)

Noda Time еще не готова к v1.0, но в основном из-за нескольких отсутствующих функций. Готовы ли вы взять на себя риск проекта с открытым исходным кодом, отличным от v1.0, или нет, конечно, решать вам, но я был бы очень рад помочь с любыми возникшими проблемами. (Я действительно пытаюсь найти реальные варианты использования, поэтому, если вам нужны какие-то недостающие функции, я вполне могу реализовать их в ожидании того, что другим понадобится то же самое.)

Noda Time использует базу данных часовых поясов zoneinfo, а не встроенную в Windows, поэтому у нее не должно быть таких же проблем.

Чтобы проверить, вы должны использовать такой код:

DateTimeZone belgradeZone = DateTimeZone.ForId("Europe/Belgrade"); // Or whatever
// Alternatively...
DateTimeZone localZone = DateTimeZone.SystemDefault;
ZonedDateTime utc = new ZonedDateTime(2011, 10, 23, 9, 0, 0, DateTimeZone.Utc);
ZonedDateTime belgrade = new ZonedDateTime(utc.ToInstant(), belgradeZone);
Console.WriteLine(belgrade.LocalDateTime);
0 голосов
/ 02 ноября 2011

.NET выполняет некоторые закулисные вычисления.Я рекомендую прочитать эту статью от Раймонда Чена о неявных преобразованиях часовых поясов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...