J'ai une table dans la base de données postgresql (version du moteur 10.11) avec une colonne appelée resettime dont le type de données est timestamptz. Le fuseau horaire par défaut de la base de données est « Australia/Sydney ».

La colonne resettime a la valeur par défaut timezone('UTC'::text, now()).

J'ai exécuté la commande suivante pour définir cette colonne dans DBEaver.

update mytable set resettime = timezone('UTC', now()) + interval '1 hour' where id = 1;

L'heure UTC actuelle est 11:47 et l'heure AEST correspondante est 21:47

Après avoir exécuté l'instruction ci-dessus, j'ai essayé d'obtenir le resettime par l'instruction suivante dans DBEaver.

select resettime from mytable where id=1

De cette déclaration, j'ai obtenu 2020-09-14 12:47:25.

Ensuite, j'exécute la commande suivante dans DBEaver.

update mytable set resettime = resettime + interval '1 hour' where resettime < timezone('UTC', now());

Après avoir exécuté cette commande, je vérifie l'heure de réinitialisation de l'enregistrement avec id = 1, j'ai trouvé que l'heure de réinitialisation était conforme à mes attentes. C'est normal.

Cependant, lorsque j'ai exécuté la même instruction de mise à jour dans mon application scala, l'heure de réinitialisation a été mise à jour en tant que 2020-09-14 13:47:25. J'ai le sentiment que l'heure de réinitialisation est toujours considérée comme l'heure AEST si j'y accède via mon application scala. Je ne veux pas changer les paramètres de fuseau horaire par défaut en UTC.

Comment dois-je m'assurer que mon application scala obtienne également le même comportement que mon accès via DBEaver ? Dans l'exemple ci-dessus, j'espère que l'heure de réinitialisation n'est pas modifiée par mon application scala pour exécuter la même instruction de mise à jour. Merci!

0
yyuankm 14 sept. 2020 à 14:53

1 réponse

Meilleure réponse

Le problème est que timezone('UTC', now()) convertit l'horodatage actuel en timestamp without time zone - le résultat est l'horodatage actuel tel qu'il apparaîtrait sur une horloge réglée sur l'heure UTC.

Ensuite, lorsque vous affectez le résultat à resettime, qui est un timestamp with time zone, la valeur qu'il a reconvertie, mais cette fois en fonction de votre réglage actuel du paramètre timezome (qui est différent de UTC).

Donc, vous demandez d'abord à quoi ressemble une horloge UTC en ce moment, puis vous interprétez ce résultat dans votre fuseau horaire actuel. En conséquence, vous vous retrouvez avec une valeur qui est décalée.

La solution simple et correcte n'est pas du tout de convertir entre les deux types d'horodatage, mais de s'en tenir à timestamp with time zone :

update mytable
set resettime = now() + interval '1 hour'
where id = 1;

Cela fera exactement ce que vous voulez.

1
Laurenz Albe 14 sept. 2020 à 12:30