Проблемы с часовым поясом с PHP и MySQL

Время моего сервера в GMT, и я делаю следующее, когда кто-то приходит в Интернет.

// Set a default timezone $defaultTimeZone = 'America/Toronto'; // load the user, if they are online... $onlineUser = new user(); if (isset($_SESSION['user_id'])) { if ($onlineUser->loadUser($_SESSION['user_id'])) { $defaultTimeZone = $onlineUser->timeZone; } } // set time zones date_default_timezone_set($defaultTimeZone); $db->query("SET SESSION time_zone = '".$defaultTimeZone."'"); 

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

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

РЕДАКТИРОВАТЬ:

Вот как я обновляю статус пользователей:

 public function updateStatus() { global $db, $common, $config; // update the user record $data = array( 'date_last_active' => new Zend_Db_Expr('NOW()') ); $db->update('users', $data, 'user_id='.$this->userId); } 

Вот моя функция, чтобы превратить дату в секундах …

 public function dateTimeToUnixTime($dateString) { if (strlen($dateString) < 10) { return ""; } $parseDateTime = split(" ", $dateString); $parseDate = split("-", $parseDateTime[0]); if (isset($parseDateTime[1])) { $parseTime = split(":", $parseDateTime[1]); } else { $parseTime = split(":", "00:00:00"); } return mktime($parseTime[0], $parseTime[1], $parseTime[2], $parseDate[1], $parseDate[2], $parseDate[0]); } 

И, наконец, как я сравниваю даты:

  $date = $oUser->dateLastActive; $lastSeen = abs($common->dateTimeToUnixTime(date('Ymd H:i:s')) - $common->dateTimeToUnixTime($date)); if ($lastSeen < 300 ) { echo "<font size='1' color='green'><strong>Online</strong></font>"; } if ($lastSeen >= 300) { echo "<font size='1' color='black'><strong>Offline</strong></font>"; } 

Solutions Collecting From Web of "Проблемы с часовым поясом с PHP и MySQL"

Трюк здесь заключается в том, чтобы знать, какой тип столбца date_last_active . У меня было достаточно опыта с TIMESTAMP и DATETIME чтобы знать, что один переводит (и выполняет) переменную сеанса MySQL time_zone, а другой – нет.

 mysql> SET SESSION time_zone = 'America/New_York'; Query OK, 0 rows affected (0.00 sec) mysql> create table timetest ( dt datetime NULL, ts timestamp NOT NULL DEFAULT 0 ); Query OK, 0 rows affected (0.06 sec) mysql> INSERT INTO timetest ( dt, ts ) VALUES ( UTC_TIMESTAMP(), UTC_TIMESTAMP() ); Query OK, 1 row affected (0.00 sec) mysql> INSERT INTO timetest ( dt, ts ) VALUES ( NOW(), NOW() ); Query OK, 1 row affected (0.00 sec) mysql> SELECT * FROM timetest; +---------------------+---------------------+ | dt | ts | +---------------------+---------------------+ | 2009-06-27 17:53:51 | 2009-06-27 17:53:51 | | 2009-06-27 13:53:54 | 2009-06-27 13:53:54 | +---------------------+---------------------+ 2 rows in set (0.00 sec) mysql> set session time_zone='UTC'; Query OK, 0 rows affected (0.00 sec) mysql> SELECT * FROM timetest; +---------------------+---------------------+ | dt | ts | +---------------------+---------------------+ | 2009-06-27 17:53:51 | 2009-06-27 21:53:51 | | 2009-06-27 13:53:54 | 2009-06-27 17:53:54 | +---------------------+---------------------+ 2 rows in set (0.00 sec) 

Итак, вот что я делаю:

  • При вставке в базу данных используйте UTC в PHP и MySQL. В my.cnf меня есть: time_zone=UTC чтобы избежать проблем в MySQL, а в PHP я date_default_timezone_set('UTC') .
  • Используйте UTC_TIMESTAMP() вместо NOW() – один – это UTC, один использует локальный (сеансовый) часовой пояс. Если вы следуете первой точке, выше, используйте UTC_TIMESTAMP ().
  • Когда вы set time_zone=' для отображения пользователю, set time_zone=' local_time_zone ' перед отображением чего-либо.
  • Если вам нужно отобразить материал, затем обновите его, обязательно скопируйте свои вызовы с соответствующими изменениями в часовом поясе в PHP и MySQL.

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

Я думаю, что функция NOW () Mysql сохраняет текущий часовой пояс, что определенно является проблемой, я бы проверял CONVERT_TZ (dt, from_tz, to_tz), это может решить вашу проблему, также я считаю, что время php () возвращает время сервера, вы может сохранить это вместо этого. единственным недостатком является либо преобразование возвращаемого значения в значение datetime / timestamp, либо сохранение его как varchar. недостатком использования convert_tz является то, что вы можете получить некоторые уродливые запросы, и вам нужно будет определять текущий часовой пояс каждый раз, когда вы его используете.

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

Прежде всего у вас есть два варианта использования MYSQL TIMEZONE или PHP TIMEZONE , не смешивайте их друг с другом, если вы хотите держаться подальше от кошмаров часовых поясов.

ЕСЛИ ВЫ ВЫБИРАЕТЕ MYSQL TIMEZONE:

ДЛЯ ВСТАВКИ:

 fieldname: yourfieldname datatype: timestamp default: CURRENT_TIMESTAMP 

ДЛЯ ОБНОВЛЕНИЯ:

 UPDATE YOUR_TABLE SET youfieldname = NOW() WHERE CONDITION; 

ДЛЯ ВЫБОРА:

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

 mysql>SET SESSION time_zone='offset'; mysql>SELECT NOW(); 

пример смещения: +05: 30 для Индии, так же найти смещение для вашего региона.

Теперь вы получите нужную дату и время из mysql.

ЕСЛИ ВЫ ВЫБИРАТЬ PHP TIMEZONE :

Просто установите часовой пояс своего желания, используя эту функцию:

 date_default_timezone_set('America/Los_Angeles'); 

ДЛЯ ВСТАВКИ:

fieldname : ваше поле

Тип данных: datetime

Используйте функцию даты PHP для хранения даты и времени:

 $sql = "INSERT INTO timetest ( YOURDATETIMEFIELD ) VALUES ('".date('Ymd H:i:s')."')"; 

ДЛЯ ОБНОВЛЕНИЯ:

 $sql = "UPDATE YOUR_TABLE SET yourdatetimefield = '".date('Ymd H:i:s')."'"; 

ДЛЯ ВЫБОРА:

 $sql = "SELECT yourdatetimefield FROM yourtable"; 

Надеюсь, это поможет вам.