Хранение даты и времени в формате UTC и преобразование их по местному времени в PHP / MySQL - PullRequest
7 голосов
/ 20 февраля 2012

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

Чтобы сформулировать мой вопрос, вот моя проблема ... Я храню «действия», предпринятые пользователем в таблице истории. Эти действия имеют метку времени на них. Пользователи могут быть со всего мира, и, следовательно, имеют разные часовые пояса. Я хочу отобразить элементы в истории и показать временные метки в местном часовом поясе.

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

Будет ли это работать для моей проблемы?

  1. Часовой пояс моего сервера будет Лос-Анджелес

  2. Сохранять метки времени как метки времени в MySQL. Насколько я понимаю, отметка времени всегда хранится как UTC. Записи будут сохранены по умолчанию как creation_date ИЛИ я явно установлю UTC_TIMESTAMP (). По сути, все записи в БД будут в формате UTC.

  3. Когда пользователь входит в систему, я получаю его часовой пояс (я сохраняю его в БД в качестве пользовательской настройки). Например, предположим, что этот человек находится в Нью-Йорке.

Здесь мой вопрос. Будет ли это работать?

  1. а) Получить данные истории. Все метки времени будут автоматически конвертированы из UTC в время Лос-Анджелеса. Элемент истории Foreach, конвертируйте метку времени Лос-Анджелеса в метку времени Нью-Йорка и эхо.

ИЛИ

  1. b) Установите часовой пояс php "date_default_timezone_set" в Нью-Йорк. Возьмите данные истории. Все метки времени по-прежнему в Лос-Анджелесе, время на сервере по-прежнему соответствует времени Лос-Анджелеса Элемент истории Foreach, просто укажите временную метку, потому что date_default_timezone_set автоматически преобразует метку времени Лос-Анджелеса в Нью-Йорк.

Будет ли работать вариант 4b? Есть ли лучший способ перевести время из Лос-Анджелеса в Нью-Йорк?

Есть ли лучший способ сделать это вообще?

Ответы [ 4 ]

5 голосов
/ 20 февраля 2012

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

<?php

$timeStampFromDatabase = 1325448000;  // 01 Jan 2012 20:00:00 GMT

date_default_timezone_set('America/Los_Angeles');
echo date('r', $timeStampFromDatabase); // Sun, 01 Jan 2012 12:00:00 -0800

date_default_timezone_set('Asia/Hong_Kong');
echo date('r', $timeStampFromDatabase); // Mon, 02 Jan 2012 04:00:00 +0800

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

3 голосов
/ 20 февраля 2012

К сожалению, date_default_timezone_set не работает так, как я думал. Как и в предыдущем примере, это сработало бы, если бы даты, с которыми я работал, были уже в формате отметки времени unix. Однако они были отформатированы в формате «Y-m-d H: i: s», и единственное, что могло измениться, это смещение по Гринвичу, которое, очевидно, не работает.

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

$datetime = new DateTime($date_to_convert);
$usertimezone = new DateTimeZone($_SESSION['timezone']); //each user has their own timezone i store in a session (i.e. - "Americas/Los_Angeles")
$datetime->setTimezone($usertimezone);
echo $datetime->format("Y-m-d H:i:s");

Полагаю, я мог бы также сделать следующее:

Pseudo code
strtotime($datetime)
date_default_timezone_set($user_timezone)
echo date(format, $datetime)

вышеизложенное, я думаю, заставит функцию date обрабатывать свою логику в заданной $ user_timezone. Оглядываясь назад, я должен был бы переводить каждый $ datetime -> unix_timestamp -> $ datetime_converted, что звучит не намного лучше, чем то, что я решил сделать.

1 голос
/ 09 февраля 2015

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

$users_timezone = 'Europe/London'; // See PHP documentation for names that can be used.
$date = new DateTime();
$date->setTimestamp($timestamp_from_database);
$date->setTimezone(new DateTimeZone($users_timezone));   
echo $date->format("H:ia jS F Y");
0 голосов
/ 22 февраля 2017

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

<?php

$TZ_UTC = new DateTimeZone('UTC'); //-->Database Timezone;
$TZ_LOCAL = new DateTimeZone('America/New_York'); //-->Expected Local Timezone from user settings;

//--Example Database Query--
while($row = mysqli_fetch_array($result, MYSQLI_ASSOC)) {
    //---If we want to show UTC timezone directy----
    echo $row['action_timestamp'];

    //---If we want to show LOCAL timezone from user settings----
    $dateObj = new DateTime($row['action_timestamp'], $TZ_UTC);
    $dateObj->setTimezone($TZ_LOCAL); //--> Here is the conversion!
    echo $dateObj->format("Y-m-d H:i:s T");
}
?>
...