Dates : confusion entre UTC, GMT, Locale, etc.

Le tout entre Backend Mysql et frontend javascript

a marqué ce sujet comme résolu.

En fait, si je reprends la chaîne, il y a plusieurs maillons :

  1. la récupération de la valeur du champ
  2. la sérialisation avant envoi
  3. la dé-sérialisation à la réception
  4. le formatage pour insertion en base
  5. la récupération depuis la base
  6. la sérialisation pour l’envoi
  7. la "reconstruction" à la réception

J’aurais déjà envie dans un premier temps de mettre UTC à la place de Europe/Paris dans la configuration du normalizer, vu qu’on sait que c’est envoyé du client formaté avec toISOString() et que du coup c’est de l’UTC. On verra vite ce qu’il en est pour le retour.

Ensuite, je ne sais pas si les données envoyées sont celles reprises depuis la BDD (donc on aurait les étapes 4, 5 et 6) ou si c’est simplement celles reprises directement après l’étape 3, ce qui permettrait de cibler une partie du problème.

+0 -0

Il n’y a pas la possibilité de convertir avant en UTC pour l’enregistrer dans la BDD, et de gérer la conversion pour l’affichage selon le client ?

Moté

Pas avec le besoin exprimé, qui est de conserver les informations de fuseau horaire. Ce que tu décris correspond au cas où tu veux gérer des instants, et où tu n’as pas de format de timestamp utilisable dans toute la chaîne : c’est l’heure UTC qui fait office de timestamp.

Concernant la version MySQL

Bon, de mon côté, j’ai vérifié, j’ai bien une version >8 de mysql sur mon environnement de travail. Ca ne marche pas, mais au moins il y a la certitude que ça devrait marcher.

Par contre, je viens de vérifier mon hébergeur actuel (nuxit) qui est en version <7.4. De ce que je vois, OVH est en version 5.6 ou 8, mais ne les ayant pas encore contacté, je ne sais pas si on peut demander à être sur une version 8.

Du coup, si de toute façon mon hébergeur probable ne peut pas me garantir que je serai en 8, au final, cette prise de tête monumentale est peut-être - en plus - inutile ; à part bien sûr pour le plaisir de comprendre l’origine d’un problème et de le résoudre.

Concernant les étapes d’Ymox

Je mettrais volontiers les étapes 1 et 2 hors de cause vu que si je passe par l’interface API elles sont automatiquement zappées et que ça ne change rien. On voit également que les étapes 5/6/7 sont probablement aussi hors de cause puisque les données sont déjà fausses en BDD. Restent les étapes 3 et 4. Là, je suis passé en "datetime_timezone: 'UTC’" dans services.yaml (Symfony\Component\Serializer\Normalizer\DateTimeNormalizer:). J’ai bien vidé le cache, refait des tests, et le problème persiste : Doctrine entre en base de données des heures h-2 sans garder l’info "Z". J’entame des recherches plus approfondies sur la désérialisation via API Platform pour voir si il y aurait d’autres méthodes de test.

Pour l’étape 3, je ne suis pas sûr de bien comprendre ce que tu proposes : c’est en lien avec ce que dit SpaceFox dans la page précédente sur MySQL ?

D’ailleurs, SpaceFox, histoire que je fasse le test correctement : quand tu dis de tester l’insertion de « le 9 septembre 2021 à 21h03 UTC+2 », ce serait comment exactement, avec quel résultat attendu ?

EDIT : à propos de la conversion des données (fausses) actuellement stockées

A priori, la fonction convert_tz va me permettre de mettre à jour mes données sans tout perdre. Il va falloir que je regarde de près si l’information du changement d’heure en hiver peut se gérer intelligemment.

En tout cas, SELECT convert_tz(opening_time, '+00:00','+2:00') from opening_hours where activity_id = 36 me renvoie des heures correctes.

EDIT 2 : à propos de l’heure d’hiver

Histoire d’en avoir le coeur net, je viens de poster un horaire au 25 décembre - donc heure d’hiver en France - et je retrouve en BDD l’heure h-1, toujours en Time Zone +0200. Je ne sais pas si ça fait avancer le schmilblick, par contre ^^

+0 -0

D’ailleurs, SpaceFox, histoire que je fasse le test correctement : quand tu dis de tester l’insertion de « le 9 septembre 2021 à 21h03 UTC+2 », ce serait comment exactement, avec quel résultat attendu ?

JeanTilapin

Je ne connais plus les outils MySQL, mais l’idée c’est d’écrire une requête insert qui enregistre une date avec un fuseau particulier (idéalement ni UTC, ni le fuseau du serveur, pour éviter les coïncidences), et une select qui va la lire, et de vérifier que tu as toujours le bon fuseau dans les informations remontées.

Histoire d’en avoir le coeur net, je viens de poster un horaire au 25 décembre - donc heure d’hiver en France - et je retrouve en BDD l’heure h-1, toujours en Time Zone +0200. Je ne sais pas si ça fait avancer le schmilblick, par contre ^^

JeanTilapin

Ça le fait avancer dans le sens où ça montre que tu as sans doute un problème avant l’insertion en base.

Bon. J’ai passé les jours derniers à avancer sur d’autres points du projet pour me changer les idées, en me donnant le temps de revenir sur cette prise de tête plus tard. Je ne sais pas si je progresse ou régresse sur le sujet :

  • je POST via l’api :
{
  "name": "jour test 2",
  "start": "2021-09-20T00:00:00.000Z",
  "end": "2021-09-20T23:59:59.000Z",
}

On me renvoie :

{
  "@context": "/api/contexts/Vacation",
  "@id": "/api/vacations/88",
  "@type": "Vacation",
  "id": 88,
  "name": "jour test 2",
  "start": "2021-09-19 22:00",
  "end": "2021-09-20 21:59",
}

En BDD j’ai 88 jour test 2 2021-09-20 00:00:00 2021-09-20 23:59:59

Sur le Front-end, par contre, je retrouve les données "-2h", même en utilisant Date.parse() ou toLocaleString().


Si je voulais complètement laisser tomber cette norme ISO que je n’arrive pas à faire fonctionner, comment être sûr de mon coup ? Après tout, tout ça concerne des horaires locaux consultés par des locaux.

  • lors de l’envoi, aucun T et Z ?
  • dans la BDD, des horaires correspondant très exactement à ce que j’ai envoyé ?
  • toujours dans la BDD, utiliser convert_tz (cf ci-dessus) pour rectifier les 3000+ horaires déjà enregistrés ?
  • modifier/ou vérifier la configuration de quelque chose dans API Platform/Symfony ?

Merci.


Edit : Bon, quand je poste sans les T et Z, le résultat est strictement identique.

Edit 2: Ah non, my bad, j’avais laissé lors d’un précédent test la configuration dans services.yaml qui stipulait timezone 'UTC’. Si je la commente, l’inscription sans T et Z fonctionne normalement.

+0 -0

Pour commencer, ton API envoie une date et heure avec fuseau horaire, mais le retour n’a pas de fuseau horaire, pas plus que le le stockage en base. Partant de là, ça ne peut pas fonctionner.

Si tu veux changer de fonctionnement, la première étape est de regarder si ton besoin fonctionnel te permet d’utiliser des instants, ou des dates et heures dépendants de l’utilisateur (donc sans fuseau horaire). Cf mon message à ce sujet plus haut dans la conversation.

Salut

Sauf erreur, il utilise MySQL qui ne permet pas vraiment d’enregistrer les dates avec le fuseau horaire dans le même champ, donc cela revient probablement à la même chose qu’utiliser datetime dans son cas, et ça ne résout pas vraiment le problème apparemment — sachant que les tests montrent que le souci se pose avant que la base de données soit impliquée.

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte