web-dev-qa-db-fra.com

Bizarreries avec AT fuseau horaire et compensations UTC

Je ne comprends pas la différence entre ces deux colonnes. L'America/Chicago Timezone est UTC-6, donc je m'attends à renvoyer le même résultat:

select timezone('America/Chicago', '2017-01-01 12:00:00'::TIMESTAMP AT TIME ZONE 'UTC'),
       timezone('UTC-6'          , '2017-01-01 12:00:00'::TIMESTAMP AT TIME ZONE 'UTC');

Cependant, le résultat est:

2017-01-01 06:00:00 | 2017-01-01 18:00:00

De plus, ce comportement est extrêmement gênant,

SELECT '1:00 -1'::time with time zone AT TIME ZONE '-1'; 
  timezone   
-------------
 03:00:00+01

Quelqu'un peut-il expliquer cela?

6
Asaf David

Un nom de temps (((((( Name transporte plus d'informations que l'abréviation ou un simple fuseau horaire - Décalage . 'UTC-6' est une "spécification de fuseau horaire de style POSIX" qui est juste une abréviation plus offset.
le manuel sur Zones de temps :

PostgreSQL vous permet de spécifier des fuseaux horaires sous trois formes différentes:

  • Un nom de fuseau horaire complet, par exemple America/New_York. [...]

  • Une abréviation de fuseau horaire, par exemple PST. [...]

  • En plus des noms de fuseau horaire et des abréviations, PostgreSQL acceptera les spécifications de fuseau horaire de style POSIX du formulaire STDoffset ou STDoffsetDST, où STD est une abréviation de zone, le décalage est un numérique offset en heures à l'ouest de UTC, et DST est une abréviation de zone d'épargne d'été en option, supposée être comprise pendant une heure avant le décalage donné.

La différence que vous observez des tiges d'une autre bizarrerie. Vous devez utiliser + au lieu de -:

timezone('UTC+6', '2017-01-01 12:00:00'::TIMESTAMP AT TIME ZONE 'UTC')

le manuel à nouveau :

Un autre problème à garder à l'esprit est que, dans les noms de zone temporelle POSIX, des compensations positives sont utilisées pour des emplacements OUEST de Greenwich. Partout ailleurs, PostgreSQL suit la Convention ISO-8601 selon laquelle les décalages positifs de Timezone sont positifs Est ​​de Greenwich.

Cependant, même après avoir fixé l'erreur de décalage, les deux expressions sont toujours pas équivalentes . Entre autres choses, un nom de fuseau horaire comme 'America/Chicago' considère également les règles de l'heure d'été (DST).

BTW, votre expression peut être simplifiée pour:

timestamptz '2017-01-01 12:00:00 +0' AT TIME ZONE 'UTC+6'

Mais vous voulez probablement le nom du fuseau horaire pour être sûr:

timestamptz '2017-01-01 12:00:00 +0' AT TIME ZONE 'America/Chicago'

En rapport:


Pour résoudre Votre deuxième exemple:

SELECT '1:00 -1'::time with time zone AT TIME ZONE '-1';

Syntaxe simplifiée et équivalente:

SELECT timetz '1:00 -1' AT TIME ZONE '-1';

Les deux instances du littéral -1 ont différent signification . Le premier décalage fait partie du littéral *timetz* indiquant un emplacement ( Est de Greenwich (conforme à la norme SQL). Le second est un Spécifications du fuseau horaire de style POSIX signifiant un décalage (( Ouest de Greenwich. En l'absence d'une spécification de zone, UTC est supposé comme base. Voir:

Notez également que le AT TIME ZONE construire renvoie timetz pour timetz entrée. Il suffit de re-basse le temps littéral sur un décalage différent. Ceci est différent de son utilisation avec timestamp/timestamptz entrée, où le type de données est également commuté.

Mais n'utilisez pas le type de données timetz (time with time zone) du tout . Il est cassé par la conception et seulement inclus dans Postgres, car cela fait partie de SQL standard. Il est utilisé explicitement découragé. Voir:

10
Erwin Brandstetter