web-dev-qa-db-fra.com

Comment comparer des horodatages avec des fuseaux horodataires différentes?

Par exemple, j'ai une table avec horodatage:

    2018-04-05 06:00:00 +01
    2018-04-05 06:00:00 +00
    2018-04-05 06:00:00 -01
    2018-04-05 04:00:00 -01

Et je veux obtenir des entrées qui sont ...

BETWEEN 2018-04-05 06:00:00+01 AND 2018-04-05 07:00:00+01

Donc, ma sortie serait:

    2018-04-05 06:00:00 +01
    2018-04-05 04:00:00 -01

L'opérateur BETWEEN gère-t-il la zone horaire différencie automatiquement et donnez-moi la sortie nécessaire?

4
7cart project

Cela fonctionne juste:

SELECT *, ts AT TIME ZONE '-01'  -- see below about '-1' vs '+1'
FROM  (
   VALUES 
   (1, timestamptz '2018-04-05 06:00:00 +01')
 , (2,             '2018-04-05 06:00:00 +00')
 , (3,             '2018-04-05 06:00:00 -01')
 , (4,             '2018-04-05 04:00:00 -01')
   ) t(id, ts)
WHERE  ts BETWEEN '2018-04-05 06:00:00+01'  -- coerced to timestamptz
              AND '2018-04-05 07:00:00+01'; -- derived from context!

Mais note plusieurs pièges et idées fausses potentielles ici!

  • Le SQL Construct BETWEEN ... AND (pas une fonction, strictement parlant; plus comme un opérateur en pratique) ne concerne pas les fuseaux horaires. Ce serait une idée fausse de la façon dont les choses fonctionnent.

  • Soyez conscient des deux types de données distincts timestamp (timestamp without time zone) et timestamptz (timestamp with time zone). Voir:

  • En particulier, le fuseau horaire décalé dans timestamptz littéraux sert uniquement de modificateur d'entrée/sortie à la valeur et est non stocké du tout . Seul l'heure UTC est stockée en interne. Voir:

  • Soyez conscient de la différence de syntaxe impaire entre Timestamp littéraux et fuseau horaire Spécificateurs (signe renversé) en raison du désaccord entre les normes POSIX et SQL:

  • La sortie que vous Afficher (avec des décalages de fuseau horaire différents) ne peuvent pas être obtenus simplement timestamptz valeurs:

    2018-04-05 06:00:00 +01
    2018-04-05 04:00:00 -01
    

    timestamptz Les valeurs sont toujours affichées Selon le paramètre timezone définition de la session. Pour obtenir les chaînes que vous affichez (pour différentes fuseaux horaires), vous devriez préserver le décalage de fuseau horaire de l'entrée et l'utiliser pour formater la sortie. (Ou stocker des littéraux d'entrée complètes comme text)

  • Enfin, notez que '2018-04-05 04:00:00 -01' transmet également le test, car c'est Exactement Le même timestamptz Valeur as '2018-04-05 06: 00: 00 + 01', il suffit de formaté différait différemment (même point dans le temps, affiché pour différentes fuseaux horaires). Ainsi Trois rangées transmettent le test dans votre exemple, pas seulement deux.

Si votre tête tourne en ce moment, considérez cette démo:

WITH tbl AS (
   SELECT *
        , split_part(tstz_string, ' ', 3) AS tz_string
        , tstz_string::timestamptz AS tstz
   FROM  (
      VALUES 
      (1, '2018-04-05 06:00:00 +01')
    , (2, '2018-04-05 06:00:00 +00')
    , (3, '2018-04-05 06:00:00 -01')
    , (4, '2018-04-05 04:00:00 -01')
      ) t(id, tstz_string)
   )
SELECT *
     , to_char(tz_string::numeric * -1, 'SG00')                                       AS tz_posix
     ,  tstz AT TIME ZONE (tz_string::numeric * -1)::text AS ts_at_org_tz
     , (tstz AT TIME ZONE (tz_string::numeric * -1)::text)::text || ' ' ||  tz_string AS tstz_org
     , (tstz AT TIME ZONE (tz_string::numeric * -1)::text)::text || ' ' ||  tz_string 
      = tstz_string                                                                   AS strings_equal
FROM   tbl;
[.____] id | Tstz_string | tz_string | TSTZ | tz_posix | TS_AT_ORG_TZ | TSTZ_ORG | strings_equal [.____] -: | : ---------------------- : --------- | | : ----------------------- | : -------- | : --------------------- | | : ------------------------- | : -------------- 
 1 | 2018-04-05 06:00:00 +01 | +01 | 2018-04-05 06: 00: 00 + 01 | -01 | 2018-04-05 06:00:00 | 2018-04-05 06:00:00 +01 | t 
 2 | 2018-04-05 06:00:00 +00 | +00 | 2018-04-05 07: 00: 00 + 01 | +00 | 2018-04-05 06:00:00 | 2018-04-05 06:00:00 +00 | t [.____] 3 | 2018-04-05 06:00:00 -01 | -01 | 2018-04-05 08: 00: 00 + 01 | +01 | 2018-04-05 06:00:00 | 2018-04-05 06:00:00 -01 | t [.____] 4 | 2018-04-05 04:00:00 -01 | -01 | 2018-04-05 06: 00: 00 + 01 | +01 | 2018-04-05 04:00:00 | 2018-04-05 04:00:00 -01 | t 

dB <> violon --- (ICI

3
Erwin Brandstetter