web-dev-qa-db-fra.com

Valeur de mise à jour dans la colonne TIMESTAMPTZ

J'ai une colonne de table avec le type de données timestamptz. Le fuseau horaire du serveur est Amérique/Denver. Passer par un problème étrange tout en insérant une valeur dans cette colonne.

Lorsque je mettez à jour la colonne à la valeur '03/11/2018 02:00:00' il aboutit à '03/11/2018 03:00:00' (+ 1 heure!).

UPDATE details 
SET    interval_start_timestamp = '03/11/2018 02:00:00'::TIMESTAMP 
WHERE  id = 2395

Le problème est seulement avec l'heure 02h00:00. 02:30:00 et d'autres valeurs comme 01:00:00 ou 01:30:00 sont l'insertion correctement.

PostgreSQL 9.5.7 sur X86_64-PC-Linux-GNU, compilé par GCC (Ubuntu 4.8.4-2Buntu1 ~ 14.04.3) 4.8.4, 64 bits

Quelqu'un peut m'aider à comprendre ce comportement?
[.____] et comment puis-je insérer les valeurs appropriées?

2
Harshal Mahajan

Vous êtes tombé victime d'un cascade de mauvaises idées.

1. DateStyle

N'utilisez pas de format dépendant des paramètres régionaux dans vos déclarations si vous pouvez l'éviter. Si les paramètres locaux changent ( lc_time et DateStyle en particulier), votre déclaration fait soudainement quelque chose de différent. '03/11/2018' est ambigu à moins d'être couplé à vos paramètres spécifiques. Toujours utiliser format ISO qui est sans ambiguïté et ne dépend pas de paramètres supplémentaires: '2018-03-11'.

2. timezone

N'attribuez pas une valeur timestamp (ou littéral) à une colonne timestamptz. La masse d'affectation dépend du paramètre Current timezone de votre session qui introduit une autre dépendance. Avec un réglage de fuseau horaire différent, votre déclaration fait quelque chose de différent. Utiliser une fonte explicite ou un timestamp with time zone littéral (timestamptz). Dans ton cas:

UPDATE details 
SET    interval_start_timestamp = '2018-03-11 02:00:00'::timestamp AT TIME ZONE 'America/Denver'
WHERE  id = 2395

En utilisant un fuseau horaire réel nom (pas une abréviation) comptes pour DST fiable - Si votre système d'exploitation est à jour, après que Postgres fonctionne avec des informations fournies par le OS sous-jacent.

En rapport:

3. DST

Qui aboutit à '2018-03-11 03:00:00'. Comme Ypercube a souligné , vous avez frappé le début de heure d'été A.K.A. heure d'été . Les horloges ont été retournées 1 heure à ce moment-là. Chaque fois qu'entre 02:00:00 et 02: 59: 59.99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999.

La simple existence de "temps d'été" (DST) est une insulte à la raison. Il devrait être aboli et ne jamais être parlé de nouveau (à l'exception des valeurs de temps historiques vouées au désordre avec cela pour toujours).

Test:

SELECT '2018-03-11 02:34:00'::timestamp AT TIME ZONE 'America/Denver' AT TIME ZONE 'America/Denver' AS t2
     , '2018-03-11 03:34:00'::timestamp AT TIME ZONE 'America/Denver' AT TIME ZONE 'America/Denver' AS t3;
[.____] T2 | T3 
: ----------------- : --------------------- 
 2018-03-11 03:34:00 | 2018-03-11 03:34:00 

dbfiddle --- (ici

3
Erwin Brandstetter