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?
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