Как лучше учитывать часовой пояс пользователя?
3758
09.05.2013, в 03:37
Возникла проблема с реализацией определённого функционала. В двух словах, задача состоит в следующем. Пользователь вводит определённые параметры, среди которых есть дата события (в будущем). Это всё сохраняется на сервере в базе. Потом, в соответствующее время (введённое ранее пользователем), что-то происходит на сервере.
При этом предполагается доступ пользователей из разных часовых поясов (отличных от часового пояса сервера). Выводить на web текущее время сервера и заставлять ориентироваться по нём – не очень user-friendly. Да и пользователи разные бывают.
Вопрос. Как проще всего сделать так, чтобы пользователь мог вводить своё локальное время и на сервере всё отработало в нужный момент?
Хранить дату в БД предполагаю в unix-timestamp, передачу от пользователя – в виде строки типа DD.MM.YYY HH:MM, которая будет парситься на сервере. Но это можно свободно изменить.
Первое, что пришло в голову – вместе с запросом передавать смещение часового пояса пользователя (new Date().getTimezoneOffset()), сравнивать со смещением пояса сервера и корректировать переданное в запросе время события.
Попытка понять, где при конвертации учитывается или не учитывается часовой пояс, и как правильно сделать это через date_default_timezone_set и MySQL SET timezone – не увенчалась успехом.
Подскажите, если есть варианты попроще. Найти что-то в и-нете не удалось.
Ответы на вопрос (6)
Сортировать по:
  • У пользователя должна быть возможность откорректировать свой часовой пояс, в котором он записывает задачи. А хранить лучше всего каждую задачу + смещение по времени. Тогда если пользователь внезапно поменяет часовой пояс — задача не собьется. Во всяком случае я бы сделал так.
  • Храню всё время в unix timestamp.
    Каждому пользователю выставляю date_default_timezone_set(), если приходит от пользователя дата не в unix timestamp — предполагается что она в этом часовом поясе, обратно конвертация аналогично будет для указанного часового пояса, всё прозрачно и просто.
    В БД всё в unix timestamp, в колонке с типом BIGINT.
  • Я храню в базе UT, выдаю пользователю тоже его, потом скриптом перевожу в часовой пояс браузера. Данный способ избавляет от лишней работы.

    выдаю примерно так:
    <span class="time" data-time="<?=time()?>">
    	<?=date('Y-m-d, H:i:s', time())?>
    </span>
    
    <script language="JavaScript">
    $(document).ready(
    	function ()
    	{
    		var times = $('.time');
    		for (var k in times)
    			makeTime(times[k]);
    	}
    );
    </script>
    
  • Хранить дату в БД предполагаю в unix-timestamp
    Очень плохая практика. Храните время в TIMESTAMP или DATETIME (различие в поясах).

    Попытка понять, где при конвертации учитывается или не учитывается часовой пояс, и как правильно сделать это через date_default_timezone_set и MySQL SET timezone – не увенчалась успехом.
    Есть удобный стандартный класс \DateTime.
  • При регистрации пользователя сохраняете в БД его часовой пояс. Узнать можно с помощью JS, либо позволить явно задать в форме.
    Далее, когда юзер создает событие, вы получаете дату в виде строки и с учетом часового пояса переводите в unix timestamp. Далее работаете с UT, не задумываясь о часовых поясах.
    Если у вас пользователи не регистрируются, запрашиваете часовой пояс при создании события
  • Для того, чтобы проводить все вычисления в таймзоне пользователя, можно сделать следующее:
    1. Тип данных для поля в MySQL: timestamp
    2. Задание таймзоны для соединения в MySQL: set time_zone = 'America/New_York' (никаких GMT+X !)
    3. Задание дефолтной таймзоны в PHP: date_default_timezone_set('America/New_York'); (и снова, никаких GMT+X! это важно)

    После этого, все даты вы будете получать из базы в указанной таймзоне, операции вида date('Y-m-d H:i:s') также будут выдавать данные согласно указанной таймзоне, сохранять данные, пришедшие от пользователя в его таймзоне вы также можете напрямую в базу.

    Чтобы MySQL принимал Olson DB identifiers (как в пункте 2) нужно залить базу таймзон (и, по хорошему, делать это регулярно). Используйте скрипт mysql_tzinfo_to_sql из стандартной поставки MySQL.

    Теперь о том, почему использовать смещения (UTC/GMT+X) плохо. Предположим, от пользователя приходит запрос на создание события, которое произойдет 12 декабря 2013 года, в 10:00. Текущее смещение времени пользователя (которое вы можете, например, получить через яваскрипт) — UTC+3. Значит ли это, что событие на сервере должно произойти 2013-12-12 10:00:00 UTC+3? Если пользователь из Калининграда — то да (поскольку летнее/зимнее время в России отменили), если пользователь из Украины (где используется перевод часов) — то нет, событие должно произойти 2013-12-12 10:00:00 UTC+2 (поскольку в Украине в этот период будет использоваться зимнее время, UTC+2).
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через TM ID
Похожие вопросы