Хранение даты и времени в формате UTC в PHP / MySQL - PullRequest
43 голосов
/ 29 августа 2009

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

Как сохранить дату в формате UTC? Я использую поле MySQL DATETIME.

При добавлении новой записи в MySQL в моем PHP-коде я использовал бы now() для вставки в MySQL DATETIME.

Нужно ли использовать что-то отличное от now() для хранения времени UTC?

Ответы [ 6 ]

43 голосов
/ 29 августа 2009

MySQL: UTC_TIMESTAMP()

Возвращает текущую дату и время UTC в качестве значения в «ГГГГ-ММ-ДД ЧЧ: ММ: СС» или Формат ГГГГММДДЧЧММСС.уууууу, в зависимости от того, является ли функция используется в строковом или числовом контексте

PHP: gmdate()

Также PHP date_default_timezone_set() используется в PHP для установки текущего часового пояса для скрипта. Вы можете установить его на часовой пояс клиента, чтобы все функции форматирования возвращали время по местному времени.

По правде говоря, мне было трудно заставить это работать, и я всегда сталкиваюсь с какой-то ошибкой. Например. Информация о времени, возвращаемая из MySQL, не форматируется как UTC, поэтому strtotime преобразует ее в местное время, если вы не будете осторожны. Мне любопытно узнать, есть ли у кого-нибудь надежное решение для этой проблемы, которое не ломается, когда даты пересекают границы медиа (HTTP-> PHP-> MySQL и MySQL-> PHP-> HTTP) также с учетом XML и RSS / Atom.

40 голосов
/ 26 сентября 2009

Я бы предложил вставить дату в часовой пояс UTC. Это избавит вас от многих головных болей в будущем с проблемами перехода на летнее время.

INSERT INTO abc_table (registrationtime) VALUES (UTC_TIMESTAMP())

Когда я запрашиваю свои данные, я использую следующий скрипт PHP:

<?php

while($row = mysql_fetch_array($registration)) { 

  $dt_obj = new DateTime($row['message_sent_timestamp'] ." UTC");
  $dt_obj->setTimezone(new DateTimeZone('Europe/Istanbul'));
  echo $formatted_date_long=date_format($dt_obj, 'Y-m-d H:i:s');
}
?>

Вы можете заменить значение DateTimeZone одним из доступных часовых поясов PHP .

7 голосов
/ 29 августа 2009

NOW() дает вам время (включая смещение часового пояса) системы, в которой работает ваша база данных. Чтобы получить дату и время UTC, вы должны использовать UTC_TIMESTAMP(), как описано в Справочном руководстве MySQL .

6 голосов
/ 28 августа 2013

https://dba.stackexchange.com/questions/20217/mysql-set-utc-time-as-default-timestamp

Цитирование всех ответов сверху по ссылке в случае удаления:

Чтобы согласиться с комментарием @ ypercube о том, что CURRENT_TIMESTAMP хранится как UTC, но извлекается как текущий часовой пояс, вы можете повлиять на настройку часового пояса вашего сервера с помощью опции - default_time_zone для получения. Это позволяет вашему поиску всегда быть в UTC.

По умолчанию опция 'SYSTEM' - это то, как установлен часовой пояс вашей системы (который может быть или не быть UTC!):

mysql> SELECT @@global.time_zone, @@session.time_zone;
+--------------------+---------------------+
| @@global.time_zone | @@session.time_zone |
+--------------------+---------------------+
| SYSTEM             | SYSTEM              |
+--------------------+---------------------+
1 row in set (0.00 sec)

mysql> SELECT CURRENT_TIMESTAMP();
+---------------------+
| CURRENT_TIMESTAMP() |
+---------------------+
| 2012-09-25 16:28:45 |
+---------------------+
1 row in set (0.00 sec)

Вы можете установить это динамически:

mysql> SET @@session.time_zone='+00:00';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @@global.time_zone, @@session.time_zone;
+--------------------+---------------------+
| @@global.time_zone | @@session.time_zone |
+--------------------+---------------------+
| SYSTEM             | +00:00              |
+--------------------+---------------------+
1 row in set (0.00 sec)

Или навсегда в вашем my.cnf:

[mysqld]
**other variables**
default_time_zone='+00:00'

Перезагрузите сервер, и вы увидите изменение:

mysql> SELECT @@global.time_zone, @@session.time_zone;
+--------------------+---------------------+
| @@global.time_zone | @@session.time_zone |
+--------------------+---------------------+
| +00:00             | +00:00              |
+--------------------+---------------------+
1 row in set (0.00 sec)

mysql> SELECT CURRENT_TIMESTAMP();
+---------------------+
| CURRENT_TIMESTAMP() |
+---------------------+
| 2012-09-25 20:27:50 |
+---------------------+
1 row in set (0.01 sec)
2 голосов
/ 21 октября 2015

Как подсказывает @Haluk, вы можете сохранить дату как UTC datetime. Я дополняю его ответ для ситуаций, когда дата, которую вы хотите вставить, происходит из кода PHP, и добавляю некоторые подробности о том, как это работает:

$pdo = new PDO('mysql:host=mydbname.mysql.db;dbname=mydbname', 'myusername', 'mypassword');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$insertStmt = $pdo->prepare("insert into test (last_modified)"
    ." values(:last_modified)");
$insertStmt->bindParam(':last_modified', $lastModified, PDO::PARAM_STR);
$lastModified = gmdate("Y-m-d H:i:s");
$insertStmt->execute();

На самом деле datetime в PHP не имеет ассоциированного с ним часового пояса. В PDO передается просто строка в одном из форматов, распознаваемых MySQL, представляющая дату в часовом поясе UTC. Например, если дата 2015-10-21 19:32:33 UTC+2:00, приведенный выше код просто говорит MySQL вставить 2015-10-21 17:32:33. gmtdate("Y-m-d H:i:s") дает вам текущую дату в таком формате. В любом случае все, что вам нужно сделать, это построить строку, представляющую дату, которую вы хотите вставить в UTC время.

Затем, когда вы читаете дату, вы должны сообщить PHP, что часовой пояс даты, которую вы только что получили, - это UTC. Для этого используйте код в ответе Халука.

0 голосов
/ 05 июля 2016

Случайно: UTC_TIMESTAMP(6) для времени с 6 цифрами микросекунд.

MySQL 5.7 +

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...