web-dev-qa-db-fra.com

Stockage de datetime en UTC dans PHP / MySQL

Partout où j'ai lu sur la conversion de l'heure en fuseau horaire d'un utilisateur, il est dit que la meilleure méthode est de stocker une date et une heure en UTC, puis d'ajouter simplement le décalage du fuseau horaire de l'utilisateur à cette heure.

Comment puis-je stocker une date en heure UTC? J'utilise le champ MySQL DATETIME.

Lors de l'ajout d'un nouvel enregistrement à MySQL dans mon PHP, j'utiliserais now() pour insérer dans MySQL DATETIME.

Aurais-je besoin d'utiliser quelque chose de différent de now() pour stocker l'heure UTC?

44
JasonDavis

MySQL: UTC_TIMESTAMP()

Renvoie la date et l'heure UTC actuelles sous forme de valeur au format 'AAAA-MM-JJ HH: MM: SS' ou AAAAAMMDJHHMMSS.uuuuuu, selon que la fonction est utilisée dans une chaîne ou dans un contexte numérique

PHP: gmdate()

PHP date_default_timezone_set() est utilisé dans PHP pour définir le fuseau horaire actuel du script. Vous pouvez définissez-le sur le fuseau horaire du client afin que toutes les fonctions de formatage renvoient l'heure à son heure locale.

En vérité, j'ai eu du mal à faire fonctionner cela et je tombe toujours dans un piège. Par exemple. les informations d'heure renvoyées par MySQL ne sont pas formatées en 'UTC' donc strtotime les transforme en heure locale si vous ne faites pas attention. Je suis curieux de savoir si quelqu'un a une solution fiable pour ce problème, qui ne se casse pas lorsque les dates franchissent les limites des médias (HTTP-> PHP -> MySQL et MySQL-> PHP-> HTTP), en considérant également XML et RSS/Atom.

44
Remus Rusanu

Je suggère d'insérer la date dans le fuseau horaire UTC. Cela vous évitera beaucoup de maux de tête à l'avenir avec des problèmes d'heure d'été.

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

Lorsque je recherche mes données, j'utilise le script PHP 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');
}
?>

Vous pouvez remplacer la valeur DateTimeZone par l'un des fuseaux horaires PHP disponibles.

40
Haluk

NOW() vous donne l'heure (y compris le décalage du fuseau horaire) du système exécutant votre base de données. Pour obtenir la date/heure UTC, vous devez utiliser UTC_TIMESTAMP() comme décrit dans le Manuel de référence MySQL .

7
user156676

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

Citant toutes les réponses du lien ci-dessus en cas de suppression:

Pour aller avec le commentaire de @ ypercube que CURRENT_TIMESTAMP est stocké en UTC mais récupéré en tant que fuseau horaire actuel, vous pouvez affecter le paramètre de fuseau horaire de votre serveur avec l'option - default_time_zone pour la récupération. Cela permet à votre récupération d'être toujours en UTC.

Par défaut, l'option est 'SYSTEM' qui est la façon dont votre fuseau horaire système est défini (qui peut ou non être 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)

Vous pouvez définir ceci dynamiquement:

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)

Ou en permanence dans votre my.cnf:

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

Redémarrez votre serveur et vous verrez le changement:

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)
6
TheFrost

Comme le suggère @Haluk, vous pouvez stocker la date sous la forme d'un UTC datetime. Je complète sa réponse pour les situations où la date que vous souhaitez insérer vient de PHP, et j'ajoute quelques détails sur la façon dont cela fonctionne:

$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();

En fait datetime in PHP n'a pas de fuseau horaire qui lui est associé. Ce qui est transmis à PDO est juste une chaîne, dans l'un des formats reconnus par MySQL, représentant la date dans le fuseau horaire UTC. Par exemple, si la date est 2015-10-21 19:32:33 UTC+2:00, le code ci-dessus indique simplement à MySQL d'insérer 2015-10-21 17:32:33. gmtdate("Y-m-d H:i:s") vous donne la date actuelle dans un tel format. dans tous les cas, il vous suffit de construire la chaîne représentant la date à insérer en heure UTC.

Ensuite, lorsque vous lisez la date, vous devez indiquer à PHP que le fuseau horaire de la date que vous venez de récupérer est UTC. Utilisez le code dans la réponse de Haluk pour cela.

2
yannick1976

Aléatoire: UTC_TIMESTAMP(6) pour l'heure avec 6 chiffres de microsecondes.

MySQL 5.7+

0
Rahim Khoja