Comment synchroniser vos fuseaux horaires PHP et MySQL

PHP et MySQL sont des processus séparés avec leurs propres configurations de fuseau horaire par défaut. Vous avez peu de chance de rencontrer des problèmes de fuseau horaire au cours de votre développement ou lors du déploiement de votre application Web unique pour votre serveur. Dans cette situation, PHP et MySQL peuvent utiliser comme paramètre l’heure du serveur.

Cependant, si:

  • Votre application permet à l’utilisateur de régler son propre fuseau horaire ?
  • Vous utilisez deux ou plusieurs applications avec des exigences de fuseau horaire différent ?
  • Votre application est installée sur un serveur partagé et que vous ne pouvez pas définir le fuseau horaire par défaut ?

De nombreux développeurs résolvent le problème en transférant la responsabilité de date/heure à PHP. Ils peuvent également convertir des dates en heures Unix (Unix timestamp), c’est-à-dire au nombre de secondes écoulées depuis le 1er janvier 1970 00:00:00 UTC jusqu’à l’événement à dater, pour simplifier la manipulation, mais il faut se méfier du bug Y2K38.

Bien qu’il s’agisse d’une solution fiable, celle-ci a plusieurs inconvénients :

  • Vous êtes obligé de vous rajouter ce traitement dans votre phase de développement
  • Votre application nécessite un traitement supplémentaire lors de la génération / réception d’une date
  • Il n’est pas facile d’étudier directement les dates dans un tableau.
  • Quelques requêtes SQL basées sur les dates sont désormais difficiles, sinon impossible. Par exemple, renvoyer toutes les données enregistrées sur un lundi.
  • Vous êtes dans l’incapacité d’utiliser les fonctions MySQL de date/heure comme now()

Heureusement, vous pouvez synchroniser les fuseaux horaires de MySQL et PHP avant de mettre à jour ou interroger votre base de données. Votre application exigera une variable de configuration unique qui définira le fuseau horaire PHP, par exemple :

[sourcecode language="PHP"]
define(‘TIMEZONE’, ‘Europe/Paris’);
[/sourcecode]

Nous allons l’utiliser pour régler le fuseau horaire par défaut de PHP :

[sourcecode language="PHP"]
date_default_timezone_set(TIMEZONE);
[/sourcecode]

Et en ce qui concerne MySQL ? Il est tout à fait possible de définir son fuseau horaire par défaut en début de chaque session. La commande est la suivante:

Note : Je vous recommande de le faire après que vous vous soyez connecté à la base de données.

[sourcecode language="SQL"]
SET time_zone=’offset’;
[/sourcecode]

offset est une chaîne représentant le décalage UTC/GMT, par exemple 4:00, +3:00, +10:30, etc… Notez que le signe +/- est essentiel, même pour zéro, et le décalage du fuseau horaire n’est pas nécessairement une heure entière.

Donc, nous allons devoir écrire un peu de PHP pour analyser le décalage du fuseau horaire et le format de la chaîne que MySQL peut comprendre. Tout d’abord, nous allons créer un nouvel objet DateTime, pour trouver le décalage en secondes, et le convertir en minutes :

[sourcecode language="PHP"]
$now = new DateTime();
$mins = $now->getOffset() / 60;
[/sourcecode]

Nous pouvons désormais entièrement calculer les heures et les minutes. La première ligne du script ci-dessous détermine si le décalage est positif ou négatif, puis convertit la valeur d’un nombre positif pour rendre le calcul plus facile :

[sourcecode language="PHP"]
$sgn = ($mins < 0 ? -1 : 1);
$mins = abs($mins);
$hrs = floor($mins / 60);
$mins -= $hrs * 60;
[/sourcecode]

La fonction PHP sprintf peut ensuite être utilisée pour formater la chaîne :

[sourcecode language="PHP"]
$offset = sprintf(‘%+d:%02d’, $hrs*$sgn, $mins);
[/sourcecode]

Enfin, nous exécutons la requête MySQL SET time_zone. Les lignes suivantes fournissent un exemple, mais vous devez utiliser votre propre bibliothèque de connexion à la base de données dès lors que c’est possible :

[sourcecode language="PHP"]
/* Connexion */
$underconnect = mysql_connect($hostname_underconnect, $username_underconnect, $password_underconnect) or trigger_error(mysql_error(), E_USER_ERROR);
/* Select DB */
$idcom = mysql_select_db($database_underconnect, $underconnect);
/* Query */
$query = mysql_query’"SET time_zone=’$offset’", $underconnect);
[/sourcecode]

Les fuseaux horaires PHP et MySQL sont désormais synchronisés au sein de votre application.

Ce problème vous a-t-il déjà réservé quelques surprises et des prises de tête ?