Manipulation de fuseaux horaires particuliers dans une base de données Postgres

mon environnement

je suis Paris, France ( UTC+1 ou CET ).

C'est 12am ( 00:00 ), nous sommes sur le 25 novembre 2016 .

Ma base de données Postgres est hébergée sur Amazon Web Services (AWS RDS) dans la région eu-west-1 .

l'enjeu

de l'Interrogation de la current_date (ou current_time ) avec un temps spécifique de la zone de jeu semble produire des résultats qui ne sont pas compatibles avec... mes croyances.

en particulier, la recherche du current_date donne un résultat différent en utilisant le CET fuseau horaire ou le UTC+1 .

exemple

SET TIME ZONE 'UTC+01';
select current_date, current_time;
+------------+--------------------+
| date       | timetz             |
+------------+--------------------+
| 2016-11-24 | 22:00:01.581552-01 |
+---------------------------------+

Non, c'était hier-deux heures.


SET TIME ZONE 'CET';
select current_date, current_time;

ou

SET TIME ZONE 'Europe/Paris';
select current_date, current_time;
+------------+--------------------+
| date       | timetz             |
+------------+--------------------+
| 2016-11-25 | 00:00:01.581552-01 |
+---------------------------------+

il y a l'heure et la date correctes.

Question

que se passe-t-il?

Est-il trop tard pour moi et j'ai confondu UTC+1 et UTC-1 ou y a-t-il quelque chose de plus grand que je ne vois pas? Les AWS RDS ont-ils un rôle à jouer?

5
demandé sur Erwin Brandstetter 2016-11-25 02:13:05

1 réponses

la question ne semble pas liée à Amazon RDS: elle a à voir avec la convention utilisée par PostgreSQL. Dans ce cas, vous do avez le nom du fuseau horaire à l'envers. Vous voulez dire 'UTC-01' où vous écrivez 'UTC+01' .

De le manuel :

une autre question à garder à L'esprit est QU'en position noms de fuseau horaire, des compensations positives sont utilisées pour les emplacements Ouest de Greenwich. Partout autrement, PostgreSQL suit la convention ISO-8601 selon laquelle le décalage horaire sont est de Greenwich.

donc chaîne de fuseau horaire utilisée pour SET TIME ZONE (et l'affichage de SHOW timezone , en conséquence) ou le AT TIME ZONE construire utiliser le panneau opposé de ce qui est affiché en timestamp ( with time zone ) littérales! C'est un désaccord très malheureux entre la norme ISO et SQL d'un côté et POSIX de l'autre. (Je pense que C'est la faute de POSIX.) Voir:

mais 'CET' ou 'UTC-01' sont tous deux potentiellement erronés pour Paris parce qu'ils ne prennent pas en compte les règles pour heure d'été .

(DST est l'un des concepts les plus débiles de l'histoire de l'humanité.)

Paris (comme la plupart de L'Europe) utilise CET en hiver et CEST en été. Vos tests avec 'CET' il se trouve simplement que le travail en novembre. Si vous essayez la même chose en été, vous obtenez le mauvais résultat.

Pour être sur le côté sûr, toujours utiliser le nom du fuseau horaire 'Europe/Paris' , qui considère règles d'heure d'été. L'appel est plus cher.

la fonction current_time prend en compte les règles DST si votre réglage de fuseau horaire en implique une. Mais 'UTC-01' est un simple décalage horaire. Je n'utilise jamais le type de données time with time zone ou current_time pour commencer. Le manuel une fois de plus:

Nous ne pas vous recommandons d'utiliser le type time with time zone (même s'il est pris en charge par PostgreSQL pour les applications traditionnelles et pour la conformité avec la norme SQL)

prendre en considération:

SELECT '2016-06-06 00:00+0'::timestamptz AT TIME ZONE 'UTC+01' AS plus_wrong
     , '2016-06-06 00:00+0'::timestamptz AT TIME ZONE 'UTC-01' AS minus_right
     plus_wrong      |     minus_right     
---------------------+---------------------
 2016-06-05 23:00:00 | 2016-06-06 01:00:00
SELECT '2016-01-01 00:00+0'::timestamptz AT TIME ZONE 'CET'    AS cet_winter
     , '2016-06-06 00:00+0'::timestamptz AT TIME ZONE 'CEST'   AS cest_summer
     , '2016-06-06 00:00+0'::timestamptz AT TIME ZONE 'CET'    AS cet_no_dst  -- CET wrong!
     cet_winter      |     cest_summer     |     cet_no_dst      
---------------------+---------------------+---------------------
 2016-01-01 01:00:00 | 2016-06-06 02:00:00 | 2016-06-06 01:00:00  -- wrong
SELECT '2016-06-06 00:00+0'::timestamptz AT TIME ZONE 'Europe/Paris' AS paris_summer
     , '2016-01-01 00:00+0'::timestamptz AT TIME ZONE 'Europe/Paris' AS paris_winter
 paris_summer         | paris_winter
----------------------+----------------------
 2016-06-06 02:00:00  | 2016-01-01 01:00:00  -- always right

Related:

2
répondu Erwin Brandstetter 2018-09-17 10:51:46