Использование часовых поясов в веб-приложении PHP

Я уже несколько часов смотрю, как наилучшим образом использовать часовые пояса в веб-приложении PHP / MySQL, найти окончательный ответ сложно. Из того, что я узнал до сих пор, лучше всего хранить всякие вещи в базе данных в UTC (исправьте меня, если я ошибаюсь).

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

<option value="Europe/London">(GMT) Greenwich Mean Time : London</option> 

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

Скажите, что пользователь из Великобритании назначает встречу в 3 часа дня 24 января 2013 года и приглашает того, кто живет в Калифорнии на эту встречу, как мне ее получить, чтобы американец увидел эту встречу в своем часовом поясе, и пользователь из Великобритании видит это в его / ее часовом поясе? (Обратите внимание, что оба пользователя зарегистрированы и установили свой часовой пояс).

Кто-нибудь имеет ясное объяснение и, возможно, некоторые примеры для этого? Или можете указать мне, где я могу это найти?

благодаря

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

MySQL и PHP (PHP 5.2 и выше) имеют собственные типы данных datetime. MySQL datetime является примитивным типом данных, а PHP 5.2 и выше предлагает встроенный класс DateTime . Тип данных datetime MySQL не включает метаданные для часового пояса, но объект PHP DateTime всегда включает часовой пояс. Если конструктор datetime PHP не указывает необязательный часовой пояс во втором аргументе, тогда конструктор datetime PHP использует переменную среды php.

Оба MySQL и PHP имеют часовой пояс по умолчанию, заданный в файлах конфигурации. MySQL использует значение datetime в конфигурационном файле для каждого соединения db, если пользователь не задает другой часовой пояс после того, как соединение запущено с помощью команды SET time_zone = [timezone]; , PHP также устанавливает переменную среды часового пояса для каждого сценария, используя часовой пояс, заданный в файле конфигурации сервера, и эту переменную среды можно переопределить с помощью функции PHP date_default_timezone_set() после запуска скрипта.

Класс PHP DateTime имеет свойство, называемое часовым поясом , которое является объектом PHP DateTimeZone . Объект DateTimeZone задается с использованием строки для точного часового пояса. Список часовых поясов является всеобъемлющим, имея сотни отдельных часовых поясов по всему миру. Временные зоны PHP будут автоматически учитывать переход на летнее время.

Когда пользователь создает дату-время в веб-приложении, создайте объект datetime PHP в часовом поясе профиля пользователя. Затем используйте метод setTimezone для изменения объекта DateTime в часовой пояс UTC. Теперь у вас есть datetime пользователя в UTC, и вы можете сохранить значение в базе данных. Используйте метод format DateTime format чтобы выразить данные как строку в формате, принятом MySQL.

Таким образом, пользователь генерирует дату-время, и вы создаете объект datetime PHP в указанном часовом поясе пользователя:

 // set using an include file for user profile $user_timezone = new DateTimeZone('America/New_York'); // 1st arg in format accepted by PHP strtotime $date_object1 = new DateTime('8/9/2012 5:19 PM', $user_timezone); $date_object1->setTimezone(new DateTimeZone('UTC')); $formated_string = $date_object1->format('Ymd H:i:s'); $query_string="INSERT INTO `t_table1` (`datetime1`) VALUES('$formated_string')"; 

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

 $query_string="SELECT `datetime1` FROM `t_table1`"; $date_object1=new DateTime($datetime_string_from_mysql, new DateTimeZone('UTC'); $date_object1->setTimezone($user_timezone); $string_for_display_in_application = $date_object1->format('m/d/Y g:i a'); 

Используя этот метод, ваши значения datetime всегда хранятся в формате UTC внутри db, и пользователь всегда испытывает значения в часовом поясе своего профиля. PHP будет корректировать время перехода на летнее время, если это необходимо для каждого часового пояса.

Один из них: это объяснение не распространяется на тип данных timestamp MySQL. Я рекомендую использовать тип данных datetime MySQL для хранения значений даты и времени, а не типа данных timestamp. Типовой тип timestamp приведен в данном руководстве.

Изменить: вы можете создать массив, содержащий каждую строку временного диапазона PHP, с помощью listIdentifiers , который является статическим методом класса DateTimeZone.

В MySQL вам нужно сделать следующее:

  1. Храните выбранный вами часовой пояс каждого пользователя в каком-либо месте, где вы можете получить его, когда делаете запросы базы данных от имени этого пользователя. Вы можете сохранить его как строку.
  2. Прямо перед тем, как вы будете работать от имени конкретного пользователя (например, для хранения или получения времени и дат встречи), SET time_zone = (stored time zone setting)

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

Редактировать:

Это работает, потому что

  1. MySQL пытается использовать UTC (универсальное время, ранее известное как среднее время по Гринвичу) для хранения данных DATETIME и TIMESTAMP в таблицах.
  2. Он может сделать это правильно, только если он знает правильный местный часовой пояс для каждого элемента данных, который он предоставляет приложениям.
  3. В приложениях, которые не заботятся о разных часовых поясах, он делает это в MySQL-сервере. См. https://dev.mysql.com/doc/refman/5.5/ru/time-zone-support.html . Большинство людей, которые запускают многонациональные и многозадачные приложения, устанавливают свои временные зоны сервера в UTC, а не в местное время, потому что это упрощает процесс сортировки.
  4. Не имеет смысла пытаться конвертировать время с UTC в местное время, если вы также не знаете дату и часовой пояс, потому что местное время включается и выключается в разное время года. Просто постарайтесь, чтобы это было правильно для всех трех из Израиля, Аризоны и Нью-Йорка, я смею! Израиль переключается между дневным и стандартным временем на Пасху и Рош-а-Шана; Аризона не переключается, и Нью-Йорк переключается на прихоть федерального законодательного органа США.
  5. Существует параметр time_zone для сессии-scope ( SET time_zone = something ). Если вы не установите его, он использует представление часового пояса в пункте 3 выше. Если вы установите его, сервер будет использовать это как часовой пояс для преобразования своего внутреннего представления в представление, которое он отправляет обратно в запросах.
  6. Вы можете получить список имен доступных часовых поясов на вашем сервере MySQL, выпустив SELECT Name from mysql.time_zone_name . Это может заполнить раскрывающееся меню, из которого пользователь может выбрать свой часовой пояс. Если этот запрос не возвращает никаких элементов, посмотрите внизу https://dev.mysql.com/doc/refman/5.5/ru/time-zone-support.html .

Таким образом, это означает, что вы можете установить настройку сеанса time_zone в часовом поясе конкретного пользователя, а затем вернуться все время в часовом поясе этого пользователя. Кроме того, любые элементы DATETIME или TIMESTAMP которые вы INSERT или UPDATE будут преобразованы из часового пояса этого пользователя во внутреннее представление MySQL, поскольку они помещаются в ваши таблицы.

Будьте осторожны: в веб-приложениях с постоянными соединениями MySQL работа над новым пользовательским запросом наследует настройку time_zone соединения. Не забудьте перезагрузить его для нового пользователя.

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

Или вы можете использовать функцию MySQL

 CONVERT_TZ(datetime,'UTC','user_time_zone') 

или аналогичные по каждому элементу.

В качестве альтернативы, Java и DotNET имеют свои собственные высококачественные системы управления часовыми поясами. Таким образом, вы можете сделать выбор для запуска своего сервера MySQL с настройкой time_zone в UTC и сделать все ваши изменения в часовом поясе в своем приложении.