Обработка часовых поясов в хранилище?

Хранить все в GMT?

Сохранить все в том виде, в каком оно было введено, со встроенным смещением?

Делаете математику каждый раз при рендеринге?

Отобразить относительное время «1 минуту назад»?

Ответов (13)

Решение

Вы должны хранить в формате UTC - если вы этого не сделаете, ваши исторические отчеты и поведение во время таких вещей, как переход на летнее время, будут ... забавными. GMT - местное время с учетом летнего времени относительно UTC (а это не так).

Презентация для пользователей в разных часовых поясах может быть настоящей мерзостью, если вы храните местное время. Если ваши необработанные данные находятся в формате UTC, легко настроить его на локальный - просто добавьте смещение пользователя, и все готово!

Джоэл говорил об этом в одном из подкастов (в обходной манере) - он сказал хранить ваши данные в максимально возможном разрешении (поиск «верность»), потому что вы всегда можете изменить их, когда они снова исчезнут. Вот почему я говорю хранить его как UTC, так как местное время вам нужно настроить для всех, кто не находится в этом часовом поясе, а это большая тяжелая работа. И вам нужно сохранить, например, действовало ли летнее время, когда вы сохранили время. Юк.

Часто в базах данных в прошлом я сохранял два - UTC для сортировки и местное время для отображения. Таким образом, ни пользователь, ни компьютер не запутаются.

Теперь, что касается отображения: Конечно, вы можете сделать «3 минуты назад», но только если вы сохраните UTC - в противном случае данные, введенные в разных часовых поясах, будут отображать такие вещи, как «-4 часа назад», что будет пугают людей. Если вы собираетесь отображать фактическое время, людям нравится, когда оно указывается в их местном времени, а если данные вводятся в нескольких часовых поясах, вы можете сделать это с легкостью, только если сохраняете UTC.

Итак, я провел небольшой эксперимент с сервером MSSQL.

Я создал таблицу и добавил строку с текущим локализованным часовым поясом (Австралия). Затем я изменил дату и время на GMT и добавил еще одну строку.

Даже несмотря на то, что эти строки были добавлены с интервалом примерно 10 секунд, они отображаются на сервере SQL, поскольку они находятся на расстоянии 10 часов.

По крайней мере, это говорит мне, что я должен хранить даты в определенной манере, что для меня добавляет веса аргументам в пользу их сохранения в формате GMT.

MS Dynamics сохраняет GMT, а затем на уровне пользователя знает ваш часовой пояс относительно GMT. Затем он отображает элементы для вашего часового пояса.

Просто подумал, что брошу это там, так как это довольно большая группа в MS, и вот как они решили с этим справиться.

Ответ, как всегда, «зависит».

Это зависит от того, что вы описываете со временем, и от того, как вам были предоставлены данные. Ключ к решению, как хранить значения времени, - это решить, теряете ли вы информацию, отбрасывая часовой пояс, а также не удивляя ваших пользователей.

Есть определенные преимущества в хранении данных в формате UTC time_t - это одно целое число, позволяющее быстро сортировать и легко хранить.

Я считаю, что проблема разбита на конкретные области:

  1. Исторические данные
  2. Будущие, краткосрочные данные
  3. Будущие, долгосрочные данные

Со следующими подклассами для каждого:

  1. Система предоставлена
  2. Предоставляется пользователем

Давайте посмотрим на них по очереди.

Предоставляемая система : я бы порекомендовал запускать системы в формате UTC, тогда вы избежите проблемы с часовым поясом и, опять же, потери информации не будет (это всегда UTC).

Исторические данные : это такие вещи, как файлы системного журнала, статистика процесса, трассировка, дата / время комментариев и т. Д. Данные не изменятся, и дескриптор часового пояса не будет изменяться задним числом. Для этого типа данных информация не теряется при сохранении информации в формате UTC независимо от часового пояса, в котором она была предоставлена. Итак, отбросьте часовой пояс.

Будущие, долгосрочные данные : это события, которые либо находятся достаточно далеко в будущем, либо будут продолжаться. Если они хранятся достаточно долго, дескрипторы часовых поясов гарантированно изменятся. Хорошим примером такого типа данных является «Еженедельное собрание руководства». Это данные, которые вводятся один раз, и ожидается, что они будут работать вечно. Для этих значений важно определить, предоставлено ли оно системой или пользователем. Для данных, предоставленных пользователем, время должно храниться в часовом поясе создателя, все остальное приводит к потере информации. Эта потеря информации становится очевидной, когда определение часового пояса изменяется и время отображается создателю как имеющее совершенно другое значение!

Как указал Bwooce, возникает некоторая путаница, когда создатель и зритель находятся в разных часовых поясах. В этом случае я ожидал бы, что приложение укажет, какие значения времени сместились из-за сдвига часового пояса с их предыдущего местоположения.

Будущие, краткосрочные данные : это данные, которые быстро станут историческими или действительны только в течение короткого периода времени. Примерами могут быть интервальные таймеры, переходы рейтингов и т. Д. Поскольку для этих данных мала вероятность того, что определение изменится между созданием значения и моментом, когда оно станет историческим, можно было бы отказаться от часового пояса. Однако я обнаружил, что эти значения имеют плохую привычку превращаться в «будущие, долгосрочные данные».

После того, как вы решили сохранить часовой пояс, следует позаботиться о том, как он хранится.

  • Не храните часовой пояс как смещение или полный дескриптор.

Если вы сохраните часовой пояс как смещение, что вы будете делать, если часовой пояс изменится? Вы просматриваете систему и полностью меняете существующие данные? Если вы это сделаете, значит, вы сделали неверные исторические значения. Хорошими примерами этой ошибки являются Oracle и iCal. Oracle хранит информацию о часовом поясе как смещение от UTC, а iCal включает полный дескриптор для часового пояса создания.

  • Сохраните это как имя.

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

Если разработчики продолжат хранить все в формате UTC, независимо от часового пояса, мы продолжим видеть проблемы, которые мы наблюдали с последним пакетом изменений часового пояса.

В одной организации секретарям приходилось распечатывать календари своих команд до даты перехода на летнее время, а затем снова распечатывать их после изменения. Наконец, они сравнили эти два и воссоздали все перенесенные встречи. Конечно, они пропустили несколько, и было несколько недель боли, пока не была достигнута старая дата перехода на летнее время и время снова не стало правильным.

Посмотрите здесь, w3c отлично справились с ответом на вопрос.

Посмотрите на варианты использования.

http://www.w3.org/TR/timezone/

Обратите внимание, что они рекомендуют хранить дату в формате UTC, а не по Гринвичу, GMT зависит от летнего времени.

Даты должны храниться в формате UTC, ЕСЛИ это данные, предоставленные пользователем, и вы НЕ МОЖЕТЕ знать, в каком часовом поясе пользователь намеревался использовать эти данные. Иногда (очень редко) вам нужно просто сохранить час, минуту, секунду, день, месяц и год. компоненты без какого-либо часового пояса, чтобы вы могли выплюнуть его обратно пользователю. Теперь для новых разработчиков или, если вы не уверены, сохраните UTC, и вы будете правы на 99%.

Но не дайте себя обмануть, полагая, что это всегда работает в 100% случаев во всех случаях. Это не.

Лично я не вижу причин не хранить все в GMT, а затем использовать локальный часовой пояс пользователя для отображения времени, которое относится к ним.

Если вы хотите отображать относительное время, вам, очевидно, все равно нужно время и сделать перевод, но если вы все же хотите сделать перевод, я думаю, что GMT по-прежнему является вашим лучшим вариантом.

Мне нравится сохранять в GMT и показывать только относительные («около 10 секунд назад», «5 месяцев назад»). В большинстве случаев пользователям не нужно видеть фактические временные метки.

Конечно, есть исключения, и в отдельном приложении их может быть много, поэтому это не может быть однозначным ответом. Вещи, требующие сильных аудиторских способностей (например, голосование), и системы, в которых время является частью предметной области (астрономия, научные исследования), могут требовать отображения истинных временных меток для пользователя.

Однако большинство приложений легче понять, используя простое относительное время.

Я обычно использую время Unix. не обязательно в будущем, но работает довольно хорошо.

Всегда храните в GMT (или UTC). Оттуда его легко преобразовать в любое значение местного часового пояса.

Выше Джош полностью прав, но мне нужно объяснить одну тонкую оговорку. Это случай, когда нет правильного ответа относительно будущих событий и часовых поясов.

Рассмотрим случай повторной встречи. Это происходит в GMT 0000 (для простоты), что составляет 1200 NZST (стандартное время Новой Зеландии) и 1000 AEST в Сиднее, Австралия.

Что должно произойти с записью при переходе на летнее время в одной зоне? Если это:

1а. Если смена TZ происходит в зоне «владельца» встречи (кто ее заказал), то попытаться оставаться в том же времени на настольных часах (например, 10:00)?
1b. Если изменение TZ происходит в одной из зон другого участника встречи, то никаких изменений

Последствия: он перемещается для всех остальных, неожиданно из-за смены TZ владельцев, но для владельца он остается «встречей в 10 утра».

'2. То же, что и выше, но в обратном порядке.

Последствия: он перемещается для владельца собрания (встреча в 10 утра становится встречей в 9 утра, или v / v), что можно ожидать, но неудобно. Время на настольных часах остается неизменным для других участников до тех пор, пока они не пройдут свой собственный TZ-переход.

Ни то, ни другое не идеально. Рассмотрим случай двух встреч, одна из которых забронирована лицом A, которое происходит в 10 часов утра по местному времени, а другая - лицом B с человеком A в качестве участника, которое происходит в 9 часов утра. Если человек A и человек B находятся в разных TZ, то изменение летнего времени может легко привести к тому, что они будут забронированы дважды.

Если вы немного отклонились в этом вопросе, тогда я вполне понимаю.

Смысл этого примера заключается в том, что для правильного выполнения любого из этих действий вам необходимо знать не только версию местного времени в формате UTC, но и TZ (а не смещение), в котором владелец был при бронировании. В противном случае у вас нет выбора, кроме как выбрать вариант 2, молча, даже не сообщая никому, что все изменилось, так как время по Гринвичу не меняется, а меняется только презентация ... верно? (нет, это ловушка, презентация имеет значение, когда встреча в 10 утра проходит сама по себе)

Я должен поблагодарить своего коллегу и друга Джейсона Поллока за это понимание. Прочтите его мнение здесь , а продолжение обсуждения iCal и VTIMEZONE - здесь.

я предпочитаю хранить все с часовым поясом. клиент может решить, в каком виде он должен быть представлен позже. Моя любимая библиотека для конвертации - PostgreSQL-Database .

Мне кажется наиболее логичным хранить все в GMT / UTC. Затем вы можете отображать дату и время в любом часовом поясе, который вам нужен.

Несколько севеатов:

  1. Если время указано только как время настенных часов и является первым представлением, то это не является абсолютно указанным временем. Вы должны (и не можете) преобразовать его в любое представление GMT. EG 9:00 каждое утро. Другими словами: это не (дата) время.
  2. Если вы сохраняете дату и время будущей встречи, вы должны использовать смещение по Гринвичу, указанное входным часовым поясом и самим моментом времени . Таким образом, если это встреча летом, назначенная зимой, например, в Западной Европе, это +2: 00, хотя обычное (зимнее время) смещение составляет +1: 00. Это решит проблему календаря, о которой упоминал Bwooce.
  3. Конечно, то же самое, что применяется при использовании правильного смещения при преобразовании в GMT, применяется при обратном преобразовании в дату и время в любом конкретном часовом поясе.

К счастью, при правильном использовании тип (.NET) DateTime позаботится обо всех неприятных деталях, связанных с хранением календарей и т. Д., И все это должно быть очень простым, если вы знаете, как это работает.