Рекомендации по летнему времени и часовому поясу

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

Если у вас есть что добавить, сделайте

Многие системы зависят от сохранения точного времени, проблема связана с изменениями времени из-за перехода на летнее время - перемещение часов вперед или назад.

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

  • Как вы справляетесь с проблемой летнего времени?
  • Какие предположения являются частью вашего решения? (поиск контекста здесь)

Как важно, если не более того:

  • Что вы попробовали, это не сработало?
  • Почему это не сработало?

Мне было бы интересно программировать, ОС, постоянство данных и другие соответствующие аспекты проблемы.

Общие ответы велики, но я также хотел бы видеть детали, особенно если они доступны только на одной платформе.

Ответ 1

Резюме ответов и других данных: (пожалуйста, добавьте свои)

Делать:

  • Всякий раз, когда вы говорите о точном моменте времени, сохраняйте время в соответствии с единым стандартом, на который не влияет переход на летнее время. (GMT и UTC эквивалентны в этом отношении, но предпочтительнее использовать термин UTC. Обратите внимание, что UTC также называется Zulu или Z time.)
  • Если вместо этого вы выберете сохранение времени с использованием значения локального времени, включите смещение локального времени для этого конкретного времени из UTC (это смещение может изменяться в течение года), чтобы впоследствии можно было однозначно интерпретировать метку времени.
  • В некоторых случаях вам может потребоваться сохранить время UTC и эквивалентное местное время. Часто это делается с двумя отдельными полями, но некоторые платформы поддерживают тип datetimeoffset который может хранить оба в одном поле.
  • При сохранении меток времени в виде числового значения используйте время Unix - это количество целых секунд с 1970-01-01T00:00:00Z (исключая високосные секунды). Если вам требуется более высокая точность, используйте вместо этого миллисекунды. Это значение всегда должно основываться на UTC, без какой-либо настройки часового пояса.
  • Если впоследствии вам может понадобиться изменить временную метку, включите исходный идентификатор часового пояса, чтобы вы могли определить, изменилось ли смещение относительно исходного записанного значения.
  • При планировании будущих событий обычно предпочтительнее местное время, а не UTC, поскольку смещение обычно меняется. Смотрите ответ и сообщение в блоге.
  • При сохранении целых дат, таких как дни рождения и годовщины, не конвертируйте в UTC или любой другой часовой пояс.
    • По возможности сохраняйте данные только для даты, которые не включают время суток.
    • Если такой тип недоступен, обязательно всегда игнорируйте время суток при интерпретации значения. Если вы не можете быть уверены в том, что время суток будет игнорироваться, выберите 12:00 полдень, а не 00:00 полночь в качестве более безопасного репрезентативного времени в этот день.
  • Помните, что смещения часового пояса не всегда являются целым числом часов (например, индийское стандартное время - UTC + 05: 30, а Непал использует UTC + 05: 45).
  • Если вы используете Java, используйте java.time для Java 8 и новее.
  • Если вы используете .NET, рассмотрите возможность использования Noda Time.
  • Если вы используете .NET без Noda Time, учтите, что DateTimeOffset часто является лучшим выбором, чем DateTime.
  • Если вы используете Perl, используйте DateTime.
  • При использовании Python, используйте pytz или dateutil.
  • Если вы используете JavaScript, используйте moment.js с расширением moment-timezone.
  • Если используется PHP> 5.2, используйте собственные преобразования часовых поясов, предоставляемые классами DateTime и DateTimeZone. Будьте осторожны при использовании DateTimeZone::listAbbreviations() - см. Ответ. Чтобы поддерживать PHP в актуальном состоянии с данными Олсона, периодически устанавливайте PECL-пакет timezonedb; смотри ответ.
  • Если вы используете C++, обязательно используйте библиотеку, которая правильно использует базу данных часовых поясов IANA. К ним относятся cctz, ICU и Говард Хиннант "tz" библиотека.
    • Не используйте Boost для преобразования часовых поясов. Хотя его API утверждает, что поддерживает стандартные идентификаторы IANA (он же "zoneinfo"), он грубо сопоставляет их с данными в стиле POSIX, не учитывая богатую историю изменений, которые могла иметь каждая зона. (Также файл вышел из строя.)
  • Если вы используете Rust, используйте Chrono.
  • Большинство бизнес-правил используют гражданское время, а не UTC или GMT. Поэтому планируйте преобразовывать временные метки UTC в локальный часовой пояс перед применением логики приложения.
  • Помните, что часовые пояса и смещения не являются фиксированными и могут меняться. Например, исторически США и Великобритания использовали одни и те же даты, чтобы "прыгнуть вперед" и "отступить". Тем не менее, в 2007 году США изменили даты, на которые меняются часы. Теперь это означает, что в течение 48 недель в году разница между лондонским и нью-йоркским временем составляет 5 часов, а в течение 4 недель (3 spring, 1 осенью) - 4 часа. Будьте внимательны к таким элементам в любых вычислениях, которые включают несколько зон.
  • Рассмотрите тип времени (фактическое время события, время вещания, относительное время, историческое время, повторяющееся время), какие элементы (временная метка, смещение часового пояса и имя часового пояса) вы должны сохранить для правильного поиска - см. "Типы времени" в этот ответ
  • Синхронизируйте файлы tzdata вашей ОС, базы данных и приложений между собой и остальным миром.
  • На серверах установите аппаратные часы и часы ОС на UTC, а не на локальный часовой пояс.
  • Независимо от предыдущего пункта, серверный код, включая веб-сайты, никогда не должен ожидать, что локальный часовой пояс сервера будет чем-то конкретным. смотри ответ.
  • Предпочитаю работать с часовыми поясами в каждом конкретном случае в коде приложения, а не глобально с помощью настроек или настроек файла конфигурации.
  • Используйте сервисы NTP на всех серверах.
  • При использовании FAT32 помните, что временные метки хранятся по местному времени, а не по UTC.
  • При работе с повторяющимися событиями (например, еженедельным телешоу) помните, что время меняется в зависимости от летнего времени и будет различным в разных часовых поясах.
  • Всегда запрашивайте значения даты и времени как включающие нижнюю границу, исключающие верхнюю границу (>=, <).

Не рекомендуется :

  • Не путайте "часовой пояс", такой как America/New_York с "смещением часового пояса", например -05:00. Это две разные вещи. Смотрите тег часового пояса вики.
  • Не используйте объект JavaScript Date для выполнения вычислений даты и времени в старых веб-браузерах, так как ECMAScript 5.1 и ниже имеет недостаток дизайна, который может неправильно использовать переход на летнее время. (Это было исправлено в ECMAScript 6/2015).
  • Никогда не доверяйте клиентским часам. Это может быть очень неправильно.
  • Не говорите людям "всегда используйте UTC везде". Этот широко распространенный совет близок к нескольким действительным сценариям, которые описаны ранее в этом документе. Вместо этого используйте соответствующую временную привязку для данных, с которыми вы работаете. (Временная метка может использовать UTC, но не следует использовать будущее расписание и значения только для даты.)

Тестирование:

  • При тестировании убедитесь, что вы тестируете страны в Западном, Восточном, Северном и Южном полушариях (фактически в каждой четверти земного шара, а значит, в 4 регионах), причем в настоящее время идет как ТЛЧ, а не (дает 8), так и страна, которая это делает. не использовать DST (еще 4, чтобы охватить все регионы, в сумме 12).
  • Проверьте переход на летнее время, т.е. Когда вы находитесь в летнее время, выберите значение времени из зимы.
  • Тестируйте граничные случаи, такие как часовой пояс UTC + 12 с DST, делая местное время UTC + 13 летом и даже места с UTC + 13 зимой
  • Протестируйте все сторонние библиотеки и приложения и убедитесь, что они правильно обрабатывают данные часового пояса.
  • Тестируйте получасовые часовые пояса, по крайней мере.

Ссылка:

Другой:

  • Лоббировать вашего представителя, чтобы положить конец мерзости, которая является DST. Мы всегда можем надеяться...
  • Лобби по стандартному времени Земли

Ответ 2

Я не уверен, что я могу добавить к ответам выше, но вот несколько моментов от меня:

Типы времени

Существует четыре разных раза, которые вы должны учитывать:

  • Время события: например, время, когда происходит международное спортивное событие, или коронация/смерть/и т.д. Это зависит от часового пояса события, а не от зрителя.
  • Время телевидения: например, конкретное телешоу транслируется в 9 вечера по местному времени по всему миру. Важно, когда вы думаете о публикации результатов (например, American Idol) на своем веб-сайте.
  • Относительное время: например: этот вопрос имеет открытую щедрость закрытия за 21 час. Это легко отобразить
  • Повторяющееся время: например: ТВ-шоу происходит каждый понедельник в 9 вечера, даже когда меняется DST.

Существует также историческое/альтернативное время. Это раздражает, потому что они не могут вернуться к стандартному времени. Например: юлианские даты, даты в соответствии с лунным календарем на Сатурне, календарь Клингонов.

Сохранение времени начала/конца в UTC работает хорошо. Для 1 вам потребуется имя часового пояса + смещение, сохраненное вместе с событием. Для 2 вам нужен локальный идентификатор времени, хранящийся в каждом регионе, и местное имя часового пояса + смещение, хранящееся для каждого зрителя (это можно извлечь из IP-адреса, если вы в хрусте). Для 3, сохранить в UTC секунд и нет необходимости в часовых поясах. 4 является частным случаем 1 или 2 в зависимости от того, является ли это глобальным или локальным событием, но вам также необходимо сохранить созданную в timestamp, чтобы вы могли определить, изменилось ли определение часового пояса до или после создания этого события. Это необходимо, если вам нужно показать исторические данные.

Время хранения

  • Всегда сохраняйте время в UTC
  • Преобразовать в локальное время на дисплее (локальный определяется пользователем, просматривающим данные)
  • При сохранении часового пояса вам нужно имя, временная метка и смещение. Это необходимо, потому что правительства иногда меняют значения своих часовых поясов (например: правительство США изменило даты DST), и ваше приложение должно обрабатывать вещи изящно... например: точная метка времени, когда эпизоды LOST показывали как до, так и после правил DST изменилось.

Смещения и имена

Примером приведенного выше может быть:

Финал Кубка мира по футболу произошло в Южной Африке (UTC + 2 - SAST) 11 июля 2010 года в 19:00 по UTC.

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

Системное время

Вам также необходимо синхронизировать файлы tzdata вашей ОС, базы данных и приложений, как друг с другом, так и с остальным миром, и тщательно тестировать при обновлении. Не удивительно, что стороннее приложение, от которого вы зависите, неправильно обрабатывало изменение TZ.

Убедитесь, что аппаратные часы установлены на UTC, и если вы используете серверы по всему миру, убедитесь, что их ОС настроены на использование UTC. Это становится очевидным, когда вам нужно копировать почасовые файлы файлов apache с серверов в несколько часовых поясов. Сортировка их по имени файла работает только в том случае, если все файлы названы с тем же часовым поясом. Это также означает, что вам не нужно делать математику с датой в голове, когда вы ssh от одной коробки к другой, и вам нужно сравнить временные метки.

Кроме того, запустите ntpd во всех ячейках.

Клиенты

Никогда не доверяйте метке времени, которую вы получаете с клиентской машины, как действительный. Например, заголовки Date: HTTP или javascript Date.getTime(). Они хороши при использовании в качестве непрозрачных идентификаторов или при выполнении математики даты в течение одного сеанса на одном и том же клиенте, но не пытайтесь перекрестно ссылаться на эти значения на то, что у вас есть на сервере. Ваши клиенты не запускают NTP и могут не иметь рабочий аккумулятор для своих часов BIOS.

Пустяки

Наконец, правительства иногда будут делать очень странные вещи:

Стандартное время в Нидерландах было ровно 19 минут и 32,13 секунды перед законом UTC от 1909-05-01 до 1937-06-30. Этот часовой пояс точно не могут быть представлены формат HH: MM.

Хорошо, я думаю, что я закончил.

Ответ 3

Это важная и удивительно сложная проблема. Истина заключается в том, что не существует полностью удовлетворительного стандарта для постоянного времени. Например, стандарт SQL и формат ISO (ISO 8601) явно недостаточны.

С концептуальной точки зрения, как правило, речь идет о двух типах данных о датах времени, и их удобно различать (эти стандарты выше): " физическое время" и "< сильное гражданское время.

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

"Гражданское" время - это спецификация даты и времени, которая следует за гражданскими нормами: точка времени здесь полностью определяется набором полей datetime (Y, M, D, H, MM, S, FS) плюс TZ ( спецификация часового пояса) (также фактически "календарь", но давайте предположим, что мы ограничиваем обсуждение григорианским календарем). Часовой пояс и календарь совместно позволяют (в принципе) отображать из одного представления в другое. Но гражданские и физические моменты времени представляют собой принципиально разные типы величин, и их следует держать концептуально разделенными и обрабатывать по-разному (аналогия: массивы байтов и символьных строк).

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

Джон записывает в своем календаре напоминание о каком-то событии в datetime 2019-Jul-27, 10:30:00, TZ = Chile/Santiago, (который компенсировал GMT-4, следовательно, соответствует UTC 2019-Jul-27 14:30:00). Но однажды в будущем страна решит изменить смещение ТЗ на GMT-5.

Теперь, когда наступит день... должен ли этот напоминающий триггер в

A) 2019-Jul-27 10:30:00 Chile/Santiago= UTC time 2019-Jul-27 15:30:00?

или

B) 2019-Jul-27 9:30:00 Chile/Santiago= UTC time 2019-Jul-27 14:30:00?

Нет правильного ответа, если не знать, что Джон концептуально имел в виду когда он сказал календарь "Пожалуйста, позвоните мне на 2019-Jul-27, 10:30:00 TZ=Chile/Santiago".

Он имел в виду "гражданский день" ("когда часы в моем городе говорят 10:30 ")? В этом случае A) является правильным ответом.

Или он имел в виду "физический момент времени", точку в континууме линии времени нашей Вселенной, скажем, "когда следующее солнечное затмение происходит ". В этом случае ответ B) является правильным.

Несколько API-интерфейсов Date/Time получают это различие правильно: среди них Jodatime, который является основой следующей (третьей!) Java API DateTime (JSR 310).

Ответ 4

Сделать четкое архитектурное разделение проблем - точно знать, с каким ярусом взаимодействует с пользователями, и изменять дату-время для/из канонического представления (UTC). Не-UTC дата-время представляет собой презентацию (соответствует локальной часовому поясу пользователей) Время UTC - это модель (остается уникальной для внутренних и средних уровней).

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

Если вы можете приобретать и поддерживать местоположение пользователя, используйте местоположение для систематического преобразования даты и времени (например,.NET-культура или SQL-таблица), но предоставляйте возможность конечным пользователям выбирать переопределения, если для ваших пользователей важна дата-время.

Если есть исторические обязательства по аудиту (например, точно сказать, когда Jo в AZ заплатил счет 2 года назад в сентябре) , то сохраняйте как UTC, так и местное время для запись (ваши таблицы преобразования будут меняться с течением времени).

Определить временную референтную часовую зону для данных, которые входят в объемный - как файлы, веб-сервисы и т.д. У компании East Coast есть центр обработки данных в CA - вам нужно спросить и узнать, что они используют в качестве стандарт вместо того, чтобы предполагать тот или иной.

Не доверяйте смещениям временной зоны, встроенным в текстовое представление даты и времени, и не соглашайтесь анализировать и следовать им. Вместо этого всегда запрашивайте, чтобы часовой пояс и/или контрольная зона были явно определены. Вы можете легко получать время с помощью PST-смещения, но время на самом деле является EST, так как время ссылки и записи клиента были просто экспортированы на сервере, который находится в PST.

Ответ 5

Вам нужно знать о базе данных Olson tz, которая доступна из ftp://elsie.nci.nih.gov/pub http://iana.org/time-zones/. Он обновляется несколько раз в год, чтобы иметь дело с часто последними изменениями в том, когда (и будет ли) переключаться между зимним и летним (стандартным и летним) временем в разных странах мира. В 2009 году последний выпуск был выпущен в 2009 году; в 2010 году это было 2010n; в 2011 году это было 2011n; в конце мая 2012 года релиз был 2012c. Обратите внимание, что существует набор кода для управления данными и фактическими данными самого часового пояса в двух отдельных архивах (tzcode20xxy.tar.gz и tzdata20xxy.tar.gz). Оба кода и данные находятся в открытом доступе.

Это источник имен часовых поясов, таких как America/Los_Angeles (и синонимы, такие как US/Pacific).

Если вам нужно отслеживать разные зоны, вам нужна база данных Olson. Как сообщали другие, вы также хотите сохранить данные в фиксированном формате — Обычно UTC - это выбранный вариант; наряду с записью часового пояса, в котором были созданы данные. Вы можете различать смещение от UTC в момент времени и имя часового пояса; это может изменить ситуацию позже. Кроме того, зная, что в настоящее время 2010-03-28T23: 47: 00-07: 00 (US/Pacific) может или не поможет вам интерпретировать значение 2010-11-15T12: 30 — который предположительно указан в PST (Тихоокеанское стандартное время), а не PDT (Pacific Daylight Saving Time).

Стандартные интерфейсы библиотеки C не очень полезны для такого рода материалов.


Данные Олсона сдвинулись, частично из-за того, что A D Olson скоро выйдет на пенсию, а отчасти из-за того, что был подан иск (в настоящее время уволен) против сопровождающих за нарушение авторских прав. База данных часовых поясов теперь управляется под эгидой IANA, авторитета интернет-назначенных номеров, а там есть ссылка на первой странице 'База данных часовых поясов. Список рассылки для обсуждения теперь [email protected]; список объявлений [email protected].

Ответ 6

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

Имейте в виду, что смещение не всегда является целым числом часов (например, индийское стандартное время - UTC + 05: 30).

Например, подходящими форматами являются кортеж (время unix, смещение в минутах) или ISO 8601.

Ответ 7

Пересечение границы "компьютерного времени" и "времени людей" - это кошмар. Главное, что нет никаких стандартов для правил, регулирующих часовые пояса и летнее время. Страны могут в любое время изменить свой часовой пояс и правила летнего времени, и они это делают.

Некоторые страны, например. Израиль, Бразилия, каждый год решают, когда им нужно летнее время, поэтому невозможно заранее знать, когда (если) будет действовать DST. Другие имеют фиксированные (ish) правила относительно того, когда действует DST. Другие страны не используют DST как все.

Временные интервалы не должны быть полными часовыми отличиями от GMT. Непал +5.45. Есть даже часовые пояса, которые составляют +13. Это означает, что:

SUN 23:00 in Howland Island (-12)
MON 11:00 GMT 
TUE 00:00 in Tonga (+13)

- одно и то же время, но 3 разных дня!

Также нет четких стандартов аббревиатур для часовых поясов и того, как они меняются в DST, поэтому вы получаете такие вещи:

AST Arab Standard Time     UTC+03
AST Arabian Standard Time  UTC+04
AST Arabic Standard Time   UTC+03

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

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

Ответ 8

Для PHP:

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

Однако PHP обновляется не так часто, как БД Olson, поэтому простое использование преобразования часовых поясов в PHP может привести к устаревшей информации о летнем времени и повлиять на правильность ваших данных. Хотя это не ожидается часто, это может произойти, и произойдет, если у вас много пользователей по всему миру.

Чтобы справиться с вышеуказанной проблемой, используйте пакет timezonedb pecl, который предназначен для обновления данных о часовых поясах PHP. Установите этот пакет так часто, как он обновляется. (Я не уверен, что обновления этих пакетов следуют точно за обновлениями Olson, но, похоже, они обновляются с частотой, которая, по крайней мере, очень близка к обновлениям Olson.)

Ответ 9

Если ваш дизайн может вместить его, избегать преобразования локального времени вместе!

Я знаю, что это может показаться сумасшедшим, но подумайте о UX: пользователи начинают приближаться, относительные даты (сегодня, вчера, в следующий понедельник) быстрее, чем абсолютные даты (2010.09.17, пятница 17 сентября). И когда вы думаете об этом больше, точность часовых поясов (и DST) важнее, чем ближе дата к now(), поэтому, если вы можете выразить даты/даты в относительном формате для +/- 1 или 2 недель, остальные даты могут быть UTC, и это не слишком важно для 95% пользователей.

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

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

Ответ 10

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

  • Хранить все в UTC.

  • Создайте таблицу TZOffsets с тремя столбцами: RegionClassId, StartDateTime и OffsetMinutes (int, в минутах).

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

Когда вам нужно вычислить местное время любого времени UTC, просто выполните следующее:

SELECT DATEADD('m', SUM(OffsetMinutes), @inputdatetime) AS LocalDateTime
FROM   TZOffsets
WHERE  StartDateTime <= @inputdatetime
       AND RegionClassId = @RegionClassId;

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

Эти данные могут быть перегорожены из общедоступного tz-базы данных.

Преимущества и сноски этого подхода:

  • В коде нет правил, вы можете легко корректировать смещения для новых регионов или диапазонов дат.
  • Вам не нужно поддерживать каждый диапазон дат или регионов, вы можете добавить их по мере необходимости.
  • Регионы не должны напрямую соответствовать геополитическим границам и избегать дублирования строк (например, большинство государств в США обрабатывают DST одинаково), вы можете иметь широкие записи RegionClass, которые ссылаются в другой таблице на большее количество традиционные списки государств, стран и т.д.
  • В таких ситуациях, как США, где начальная и конечная дата DST изменилась за последние несколько лет, с этим довольно легко справиться.
  • Так как поле StartDateTime также может хранить время, стандартное время перехода 2:00 AM выполняется легко.
  • Не везде в мире используется 1-часовой DST. Это легко справляется с этими случаями.
  • Таблица данных является кросс-платформенной и может быть отдельным проектом с открытым исходным кодом, который может использоваться разработчиками, которые используют практически любую платформу базы данных или язык программирования.
  • Это можно использовать для смещений, которые не имеют никакого отношения к часовым поясам. Например, 1-секундные корректировки, которые время от времени могут корректироваться для вращения Земли, исторические корректировки и в пределах григорианского календаря и т.д.
  • Так как это в таблице базы данных, стандартные запросы отчетов и т.д. могут использовать данные без отключения кода бизнес-логики.
  • Это также относится к смещениям часовых поясов, если вы этого хотите, и может даже учитывать особые исторические случаи, когда регион назначается другому часовому поясу. Все, что вам нужно, это начальная дата, которая присваивает часовой пояс для каждого региона с минимальной датой начала. Это потребует создания по крайней мере одного региона для каждого часового пояса, но позволит задать интересующие вас вопросы: "Какая разница в местном времени между Юмой, Аризоной и Сиэтлом, Вашингтон, 2 февраля 1989 года в 5:00?" (Просто вычтите один SUM() из другого).

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

Ответ 11

Я ударил это по двум типам систем: "системам планирования сдвига (например, factory работники" ) и "системам управления газом"...

23 и 25-часовые длинные дни - это боль, с которой можно справиться, так что это 8-часовой сдвиг, который занимает 7 часов или 9 часов. Проблема заключается в том, что вы обнаружите, что у каждого клиента или даже отдела клиента есть разные правила, которые они создали (часто без документирования) на то, что они делают в этих особых случаях.

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

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

Ответ 12

У меня недавно возникла проблема в веб-приложении, где на Ajax после обратной связи datetime, возвращающийся к моему серверному коду, отличался от того, что было передано datetime.

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

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

Мое учение: Не используйте расчеты даты и времени JavaScript в веб-приложениях, если только вы НЕОБХОДИМО выполнить.

Ответ 13

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

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

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

В некоторых языках локальный часовой пояс может легко входить в код приложения. Например, метод DateTime.ToUniversalTime в .NET будет конвертировать из локального часового пояса в UTC, а свойство DateTime.Now возвращает текущее время в локальном часовом поясе. Кроме того, конструктор Date в JavaScript использует локальный часовой пояс компьютера. Есть много других подобных примеров. Важно практиковать защитное программирование, избегая любого кода, который использует настройку локального часового пояса компьютера.

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

Ответ 14

Для Интернета правила не так сложны...

  • Серверная, используйте UTC
  • Клиентская сторона, используйте Olson
    • Причина: UTC-смещения не являются безопасными для летнего времени (например, в Нью-Йорке - EST (UTC - 5 часов) в течение года, EDT (UTC - 4 Hours) в конце года).
    • Для определения часового пояса на стороне клиента у вас есть два варианта:
      • 1) Установили ли пользовательскую зону (безопаснее)
      • 2) зона автоматического обнаружения

Остальное - это просто UTC/локальное преобразование, используя ваши библиотеки datetime на стороне сервера. Хорошо идти...

Ответ 15

Держите серверы в UTC и убедитесь, что все они настроены для ntp или эквивалентного.

UTC избегает проблем с летним временем, а серверы вне синхронизации могут вызывать непредсказуемые результаты, которые требуют времени для диагностики.

Ответ 16

Будьте внимательны при работе с отметками времени, хранящимися в файловой системе FAT32, - они всегда сохраняются в локальных координатах времени (включая DST - см. msdn article). Сгорел на этом.

Ответ 17

Еще одна вещь, убедитесь, что на сервере установлен обновленный патч для летнего времени.

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

Оказывается, в конце концов это были серверы. Они просто нуждались в обновленном исправлении (Windows Server 2003).

Ответ 18

PHP DateTimeZone::listAbbreviations() вывод

Этот метод PHP возвращает ассоциативный массив, содержащий некоторые "основные" часовые пояса (например, CEST), которые сами по себе содержат более конкретные "географические" часовые пояса (например, Европа/Амстердам).

Если вы используете эти часовые пояса и их информацию о смещении /DST, чрезвычайно важно реализовать следующее:

Кажется, что все разные конфигурации смещения /DST (включая исторические конфигурации) каждого часового пояса включены!

Например, Европа/Амстердам можно найти шесть раз на выходе этой функции. Два события (смещение 1172/4772) относятся к Амстердамскому времени, использованному до 1937 года; два (1200/4800) относятся к тому времени, которое использовалось между 1937 и 1940 годами; и два (3600/4800) относятся к времени, используемому с 1940 года.

Следовательно, вы не можете полагаться на информацию о смещении /DST, возвращаемую этой функцией, как правильную/используемую в настоящее время!

Если вы хотите узнать текущее смещение /DST определенного часового пояса, вам нужно будет сделать что-то вроде этого:

<?php
$now = new DateTime(null, new DateTimeZone('Europe/Amsterdam'));
echo $now->getOffset();
?>

Ответ 19

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

Внутренне, сохраняйте отметки времени в чем-то вроде civil-time-seconds-from-epoch. epoch не имеет особого значения (я предпочитаю Unix эпоха), но это делает вещи проще, чем альтернатива. Представьте, что прыжки секунд не существуют, если вы не делаете то, что им действительно нужно (например, отслеживание спутников). Отображение между отметками времени и отображаемым временем является единственной точкой, в которой должны применяться правила DST; правила часто меняются (на глобальном уровне, несколько раз в год, обвиняют политиков), поэтому вы должны быть уверены, что не скопируете картографирование. Olson База данных TZ бесценна.

Ответ 20

Если вам удается поддерживать системы баз данных, которые работают с активным DST, внимательно проверьте, нужно ли их отключать во время перехода осенью. Mandy DBS (или другие системы) не любят пропускать одну и ту же точку в (локальном) времени дважды, что точно происходит, когда вы поворачиваете назад осенью. SAP решил это с помощью (IMHO действительно опрятного) обходного пути - вместо того, чтобы возвращать часы, они просто позволяют внутренним часам работать на половине обычной скорости в течение двух часов...

Ответ 21

Используете ли вы .NET framework? Если да, позвольте мне представить вам тип DateTimeOffset, добавленный с .NET 3.5.

Эта структура содержит как a DateTime, так и Offset (TimeSpan), которая определяет разницу между датой и временем экземпляра DateTimeOffset и скоординированным универсальным временем (UTC).

  • Статический метод DateTimeOffset.Now возвращает DateTimeOffset экземпляр, состоящий из текущего (локального) времени и локального смещения (как определено в региональной информации операционной системы).

  • Статический метод DateTimeOffset.UtcNow возвращает DateTimeOffset экземпляр, состоящий из текущего времени в UTC (как если вы были в Гринвиче).

Другими полезными типами являются TimeZone и TimeZoneInfo.

Ответ 22

Для тех, кто борется с этим на .NET, посмотрите, стоит ли использовать DateTimeOffset и/или TimeZoneInfo.

Если вы хотите использовать часовые пояса IANA/Olson, или найти встроенные типы недостаточны для ваших нужд, проверьте Noda Time, который предлагает гораздо более умный API для даты и времени для .NET.

Ответ 23

Просто хотел указать две вещи, которые кажутся неточными или, по крайней мере, запутанными:

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

Для (практически) всех практических вычислительных целей UTC, по сути, является GMT. Если вы не видите временные метки с дробной секундой, вы имеете дело с GMT, что делает это различие избыточным.

Включить локальное смещение по времени как есть (включая смещение DST), когда сохранение временных меток.

Временная метка всегда отображается в GMT и, следовательно, не имеет смещения.

Ответ 24

Вот мой опыт: -

(не требуется сторонняя библиотека)

  • На стороне сервера сохраняйте время в формате UTC, чтобы все значения даты и времени в базе данных находились в одном стандарте независимо от местоположения пользователей, серверов, часовых поясов или летнего времени.
  • На уровне пользовательского интерфейса или в сообщениях электронной почты, отправленных пользователю, вам нужно показать время в соответствии с пользователем. В этом случае вам нужно иметь смещение часового пояса пользователя, чтобы вы могли добавить это смещение в значение UTC базы данных, которое приведет к локальному времени пользователя. Вы можете либо принять смещение часового пояса пользователя при их регистрации, либо автоматически обнаружить их на веб-и мобильных платформах. Для веб-сайтов функция JavaScript getTimezoneOffset() - это стандарт с версии 1.0 и совместимый со всеми браузерами. (Ссылка: http://www.w3schools.com/jsref/jsref_getTimezoneOffset.asp)

Ответ 25

видео о часовых поясах на YouTube на канале Computerphile также есть приятное и интересное описание темы, Примеры включают:

  • Самоа (остров в Тихом океане) переводит свой часовой пояс вперед на 24 часа, чтобы облегчить торговлю с Австралией и Новой Зеландией,
  • Западный берег, где 2 популяции людей следуют за часовыми поясами,
  • 18-й век меняется на юлианский календарь на по-григориански (что произошло в XX веке в России).

Ответ 26

Собственно, kernel32.dll не экспортирует SystemTimeToTzSpecificLocation. Однако он экспортирует следующие два: SystemTimeToTzSpecificLocalTime и TzSpecificLocalTimeToSystemTime...

Ответ 27

Никогда не полагайтесь только на конструкторы вроде

 new DateTime(int year, int month, int day, int hour, int minute, TimeZone timezone)

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

Ответ 28

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

Несколько лет назад операционная система Android использовала спутники GPS для получения информации о времени UTC, но проигнорировала тот факт, что спутники GPS не используют скачки секунд. Никто не заметил, пока не возникла путаница в канун Нового года, когда пользователи телефонов Apple и пользователи телефонов Android сделали свои обратные отсчеты примерно на 15 секунд друг от друга.

Я думаю, что с тех пор он был исправлен, но вы никогда не знаете, когда эти "мелкие детали" вернутся, чтобы преследовать вас.

Ответ 29

  • Никогда, никогда не сохраняйте местное время без его UTC-смещения (или ссылки на часовой пояс) - примеры того, как это не делать, включают FAT32 и struct tm в C.¹
  • Понять, что часовой пояс представляет собой комбинацию
    • набор смещений UTC (например, +0100 зимой, +0200 летом)
    • когда происходит переключение (которое может меняться со временем: например, в 1990-х годах ЕС согласовал переход на последние воскресенья в марте и октябре, в 02:00 стандартного времени /03: 00 DST; ранее это различалось между государствами-членами).

¹ Некоторые реализации struct tm сохраняют смещение UTC, но это не превратило его в стандарт.

Ответ 30

При работе с базами данных (в частности MySQL, но это относится к большинству баз данных), мне было трудно хранить UTC.

  • Базы данных обычно работают с сервером datetime по умолчанию (т.е. CURRENT_TIMESTAMP).
  • Вы не сможете изменить часовой пояс сервера.
  • Даже если вы можете изменить часовой пояс, у вас может быть сторонний код, который ожидает, что часовой пояс сервера будет локальным.

Мне было проще просто хранить дату и время сервера в базе данных, а затем позволить базе данных преобразовать сохраненное datetime в UTC (то есть UNIX_TIMESTAMP()) в операторы SQL. После этого вы можете использовать datetime как UTC в своем коде.

Если у вас есть 100% контроль над сервером и всем кодом, вероятно, лучше изменить часовой пояс сервера на UTC.