2016-03-29 2 views
1

Я получаю неожиданный DateTime при преобразовании из:Неправильное время использования TimeZoneInfo.ConvertTime()

(UTC) Dublin, Edinburgh, Lisbon, London в (UTC-08:00) Baja California

Ниже приведен код, который я использую. Я ожидаю, что serverDateTime будет 29/03/2016 00:00:01 (-8 часов), но вместо этого я получаю 28/03/2016 23:00:01 - это разница в 9 часов.

private static void Main(string[] args) 
    { 
     ReadOnlyCollection<TimeZoneInfo> timeZones = TimeZoneInfo.GetSystemTimeZones(); 
     TimeZoneInfo localTimeZone = timeZones.FirstOrDefault(tz => tz.DisplayName.Contains("London")); 
     TimeZoneInfo serverTimeZone = timeZones.FirstOrDefault(tz => tz.DisplayName.Contains("California")); 
     DateTime clientDateTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 29, 8, 0, 1); 
     DateTime serverDateTime = TimeZoneInfo.ConvertTime(clientDateTime, localTimeZone, serverTimeZone); 
    } 

Моей локальная машина находится в Великобритании, которая в настоящее время UTC + 1, и Baja - Калифорния в настоящее время UTC-7, поэтому я ожидаю, чтобы получить 8-часовую разницу в, вместо 9. Что я Я делаю неправильно?

Заранее спасибо.

+0

Это * не * UTC (+00: 00), это просто часовой пояс Лондона, который уже использует DST (+1: 00). Я буду держать пари, что правила DST отличаются в Калифорнии. –

+0

BTW это * далеко * проще использовать NodaTime для работы со временем. Там * есть * Часовой пояс Windows, который соответствует UTC, но я еще не нашел нужный индекс. –

+0

Почему вы конвертируете время? Время конвертирования в большинстве случаев не требуется. Только время, которое действительно необходимо, - это когда вы вводите данные, которые были собраны в другой часовой пояс. Все компьютеры хранят время в UTC и по умолчанию используют настройки часового пояса при вводе и отображении времени. Преобразование времени может закончиться временем, которое не является UTC. – jdweng

ответ

5

Несколько вещей:

  • "(UTC-08:00) Baja California" относится к Baja California, Mexico - не Калифорния, США.
  • Эта запись зоны соответствует мексиканским правилам летнего времени, которые doesn't start DST until April 3rd this year. Таким образом, эта запись находится на UTC-8, объясняя разницу во времени, которую вы наблюдали.
  • Эта конкретная запись на самом деле неправильная в Windows, так как выясняется, что все состояние Baja California соответствует правилам США в отношении летнего времени, а не мексиканских правил.

    • Существует обширное многопоточное обсуждение этого в the tz mailing list archives в октябре и ноябре 2015 г. Это привело к соответствующему IANA зоны America/Santa_Isabelbeing deprecated with release 2016a. Теперь он ссылается на America/Tijuana, который уже соблюдал правила США по летнему времени.
    • Microsoft еще не внесла аналогичные изменения в свои данные, но, скорее всего, это произойдет в будущем обновлении данных часового пояса Windows. (Я уже передал это соответствующему персоналу.) Тем временем используйте "(UTC-08:00) Pacific Time (US & Canada)" - даже если вы говорите о Баха-Калифорния, Мексика.
  • Не пытайтесь найти часовой пояс по его DisplayName. Эти значения будут отличаться в зависимости от языка операционной системы. Вместо этого используйте TimeZoneInfo.FindSystemTimeZoneById. Свойства Id не локализованы. Кроме того, Microsoft считает, что значения Id являются стабильными идентификаторами, и поэтому они не будут меняться с будущими обновлениями. Значения DisplayName были изменены в прошлом и могут действительно измениться в будущем.

    • Используйте ID "GMT Standard Time" для "(UTC) Dublin, Edinburgh, Lisbon, London"
    • Используйте ID "Pacific Standard Time" для "(UTC-08:00) Pacific Time (US & Canada)"
    • Идентификатор "Pacific Standard Time (Mexico)" для "(UTC-08:00) Baja California" - но по причинам, которые я описал, не используйте эту запись.
  • Действительно, вы не должны касаться часового пояса на сервере вообще. Сервер должен быть связан только с UTC.(Обратите внимание, что Лондон не UTC, так как он переключается на BST летом)

  • Я не уверен, что вы намеревались с этой линией:

    DateTime clientDateTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 29, 8, 0, 1); 
    

    дергает за месяц и год от DateTime.Now будет использовать часовой пояс сервера. Затем вы объединяетесь с фиксированным днем ​​29 и фиксированным временем в 8:00:01. Это провалится в феврале не-високосного года (когда в месяце всего 28 дней), а также может давать плохие даты, когда дата сервера не в том же месяце и году, что и клиент (например, около перехода от одного месяца к другому).

Смежные вопросы