Одна очень важная вещь, которую нужно понять о дате/времени, заключается в том, что нет единственно правильного способа сделать все. Распространенный ответ «использовать UTC» не всегда применим. Контекст очень важен, и существуют различные методы и подходы, основанные на том, что представляют ценности, с которыми вы работаете. Если бы вы могли уточнить, для чего они используются в вашем приложении, я соответствующим образом обновлю свой ответ. А пока я попытаюсь рассмотреть конкретные моменты, которые вы уже подняли:
#1 - Часовой пояс сервера
Хранение вашего сервера в UTC — это лучшая практика, и вы также можете ожидать этого от облачных провайдеров, таких как Azure или AWS. Но это не то, от чего вы должны зависеть. Ваш сервер должен быть настроен на любой часовой пояс, чтобы это не повлияло на ваше приложение. Пока часы синхронизированы с сервером NTP, выбор часового пояса не имеет значения.
Итак, как вы гарантируете это? Просто убедитесь, что ваше приложение избегает всего следующего:
DateTime.Now
DateTimeKind.Local
TimeZone
(весь класс)
TimeZoneInfo.Local
DateTime.ToLocalTime()
DateTime.ToUniversalTime()
(потому что предполагается, что ввод является локальным)
- Разное другие методы, предполагающие локальный ввод или вывод, такие как
TimeZoneInfo.ConvertTimeToUtc(DateTime)
(эта конкретная перегрузка не использует часовой пояс, поэтому предполагается локальный часовой пояс)
См. также мою запись в блоге: Дело против DateTime.Now а>.
Обратите внимание, что я не включил DateTimeOffset.Now
в список. Хотя это немного дизайнерский запах, он по-прежнему «безопасен» в использовании.
#2 - Что хранить
Я предлагаю вам прочитать мой ответ на DateTime vs DateTimeOffset. Это должно прояснить некоторые вещи. Не повторяя всего этого, главное, что, хотя оба точно представляют момент времени, DateTimeOffset
обеспечивает перспективу, а UTC DateTime
- нет.
Вы также спросили, когда следует хранить файл TimeZoneInfo.Id
. Есть как минимум два сценария, когда это необходимо:
Если вы записываете события в прошлом или настоящем и планируете разрешить изменения записанных меток времени. Вам нужен часовой пояс, чтобы определить, каким должно быть новое смещение или как новый ввод преобразуется обратно в UTC.
Если вы планируете время на будущее, вам понадобится часовой пояс как часть шаблона повторения (даже для одного случая). См. здесь и здесь также (в то время как для других языков применяются те же принципы).
Опять же, точный ответ зависит от того, что именно представляют временные метки. Нет единого кольца, которое бы управляло ими всеми.
#3 - Безопасность клиента
Если это клиент .NET, конечно, вы можете конвертировать там. Но я думаю, вы спрашиваете о клиентском браузере JavaScript.
«Безопасный» — понятие относительное. Если вы просите о точном совершенстве, то нет. JavaScript небезопасен для этого из-за ошибки в спецификации ECMAScript (с ES1 по ES5.1. Работа над ES6 ведется). Вы можете прочитать больше в моем блоге: JavaScript Date type ужасно сломан.
Однако, если вы работаете с относительно актуальными данными, а пользователи вашего приложения не находятся в той части мира, где часовые пояса изменчивы, или вам не требуются точные результаты в 100% случаев, то вы можете «безопасно "используйте JavaScript для преобразования в местный часовой пояс пользователя.
Вы можете избежать некоторых этих проблем с библиотеками, которые реализуют IANA TZDB в JavaScript, например те, которые я перечисляю здесь. Но многие из них все еще зависят от JS Date
, поэтому у них все еще есть проблемы. (Примечание: я работаю над библиотекой JS, которая будет противостоять этому, но она еще не готова поделиться).
Преобразования на стороне сервера — гораздо лучший выбор, если вы можете запросить у пользователя часовой пояс. В большинстве случаев я думаю, что это выполнимо.
Вы можете рассмотреть вопрос об использовании средства выбора часового пояса на основе карты, такого как этого или вот этот. Оба из них потребуют от вас использования часовых поясов IANA, что для .NET означает использование Noda Time, что в любом случае является отличной идеей ( ПО МОЕМУ МНЕНИЮ).
# 4 - Летнее время
При вашем текущем подходе переход на летнее время будет учитываться в определении текущих правил перехода на летнее время для часового пояса, который пользователь установил для своего локального браузера. (Опять же, обратитесь к моему сообщению в блоге, чтобы узнать, почему это так).
Преобразование из любого значения со смещением (будь то -03:00
или Z
), которое проходит через объект Date
(что, я полагаю, сделает фильтр Angular), будет правильно преобразовано в конкретную временную метку unix.
Ошибки, которые могут возникнуть при преобразовании летнего времени для предыдущих правил летнего времени, связаны с тем, что переход от временной метки unix внутри объекта Date
к местному часовому поясу всегда будет предполагать, что применимо текущее правило летнего времени, даже если время попало в период, который имел другое правило.
person
Matt Johnson-Pint
schedule
09.12.2013