Руководства

Локализация формата даты и времени по часовому поясу посетителя

Временную метку, показанную в часовом поясе вашего сервера, правильно поймёт почти никто, кроме тех, кто находится в том же поясе, а для сайта с посетителями со всего мира это почти что никто.

Как узнать часовой пояс посетителя

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

GET /v1/ip?ip=203.0.113.77
{
  "status": "ok",
  "ip": "203.0.113.77",
  "version": 4,
  "found": true,
  "country": "Brazil",
  "country_code": "BR",
  "region": "Rio de Janeiro",
  "city": "Rio de Janeiro",
  "postcode": "20040",
  "lat": -22.9068,
  "lon": -43.1729,
  "timezone": "America/Sao_Paulo",
  "asn": 5566,
  "org": "Example ISP"
}

Преобразование сохранённых временных меток

Храните каждую временную метку в базе данных в UTC, как обычно, и преобразуйте её в местный пояс посетителя только при отображении, на сервере, с помощью найденного идентификатора часового пояса. Поскольку этот сайт отрисовывает всё на сервере без клиентского JavaScript, и преобразование, и форматирование происходят до отправки страницы, а не потом в браузере.

local_time = convert_to_timezone(stored_utc_timestamp, "America/Sao_Paulo")

Второй пример: время подтверждения заказа

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

Не только преобразование, но и форматирование

Часовой пояс и формат связаны, но это отдельные решения. Посетителю из пояса, где обычно используют 24-часовой формат времени и порядок даты «день, месяц, год», полезно форматирование, соответствующее этому, а не просто сдвинутый час, записанный в формате, который всё равно выглядит чужим. Если вы хотите пойти дальше простой корректировки часа, сочетайте country_code из того же определения IP с небольшой таблицей форматов.

Распространённая ошибка, которой стоит избегать

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

Особый случай: смещения не на целый час

Не каждый часовой пояс смещён от UTC на целое число часов. Некоторые смещены на 30 или 45 минут, а не на полный час. Если полагаться на библиотеку дат, которая понимает полный идентификатор часового пояса IANA, а не упрощённое смещение только в часах, это обрабатывается правильно без какого-либо специального кода с вашей стороны. Поля utc_offset и abbreviation из документации по определению часового пояса пригодятся, если вы хотите явно показать смещение рядом с преобразованным временем.

Кэширование пояса на время сеанса

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

Сколько стоит локализация всего сайта

Одно определение на новый сеанс покрывает локализацию всех временных меток, показанных во время этого визита: один запрос, сколько бы дат ни было на странице. Так даже сайт с большим количеством контента остаётся далеко в пределах 2 500 бесплатных запросов в день, которые входят в каждый ключ.

Правильное местное время и форматирование дат на всём сайте сводятся к одному определению за сеанс и последовательной отрисовке на сервере после этого. Документация по определению IPv4 и документация по определению часового пояса описывают оба способа узнать пояс.