doctrine
Symfony

Stocker des dates avec leur timezone, avec Doctrine

Chez netinfluence nous réalisons une application déployée sur les caisses self-service des boutiques Nespresso aux quatre coins de la planète. Cette application remonte des évènements jusqu’aux sièges en Europe, et tantôt il est utile de connaître l’heure Suisse de l’évènement, tantôt l’heure locale dans la boutique. Il faut donc stocker ces dates avec un maximum d’information.
Doctrine propose un type datetimetz, mais celui-ci n’est pas supporté par MySQL (indiqué dans une page de la documentation pas évidente à trouver). Il faut trouver une autre solution.

L’approche serait de stocker un DateTime d’un côté, le timezone de l’autre. Avec Doctrine il est possible de faire un type personnalisé, mais un type n’est appliqué que sur une seule colonne de la base. Il faut donc trouver un autre moyen.
La première idée et la plus simple est d’utiliser les setters/getter de notre entité pour lire ou écrire simultanément un $datetime et une colonne $timezone:

On voit qu’il y a un problème: lorsque Doctrine remplit le champ Event::$datetime avec la valeur récupérée depuis la BDD, il utilise le timezone de PHP (du serveur, de php.ini). Et ce n’est pas quelque chose de facilement configurable (aucune extension possible dans le code de Doctrine…). On se retrouve donc avec une valeur « fausse » dans Event::$datetime, avec un mauvais décalage, à laquelle il ne faudra surtout pas accéder directement.
Une solution plus élégante est de créer un type Doctrine, qui va se charger de la conversion en UTC, on aura donc une valeur de Event::$datetime toujours consistante, ce qui rend notre code un petit plus robuste:

J’espère que cet article vous permettra d’éviter de vous faire piéger!

PS: je ne saurais trop vous recommander de toujours utiliser que des DateTimeImmutable, il est très facile de perdre le fil de ce que l’on fait avec des DateTime classiques.

Visited 246 times, 1 visit(s) today