たとえば、タイムスタンプを含むテーブルがあります。
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
そして、私は...であるエントリを取得したいです.
BETWEEN 2018-04-05 06:00:00+01 AND 2018-04-05 07:00:00+01
だから私の出力は:
2018-04-05 06:00:00 +01
2018-04-05 04:00:00 -01
演算子BETWEEN
はタイムゾーンの違いを自動的に処理し、必要な出力を提供しますか?
これはうまくいきます:
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!
しかし、ここに注意いくつかの落とし穴と潜在的な誤解があります!
SQL構文BETWEEN ... AND
(関数ではなく、厳密に言えば、実際には演算子のようです)はタイムゾーンに関係しません。それは物事がどのように機能するかについての誤解でしょう。
2つの異なるデータ型timestamp
(timestamp without time zone
)およびtimestamptz
(timestamp with time zone
)。見る:
特に、timestamptz
リテラルのタイムゾーンオフセットは、値への入力/出力修飾子としてのみ機能し、まったく保存されません。内部では、対応するUTC時刻のみが保存されます。見る:
POSIXとSQL標準の不一致により、タイムスタンプ literals とタイムゾーン specifiers (反転符号)の間の奇妙な構文の違いに注意してください。
show (異なるタイムゾーンオフセットで)の出力は、単にtimestamptz
値を返すだけでは達成できません。
2018-04-05 06:00:00 +01 2018-04-05 04:00:00 -01
timestamptz
値は、セッションのtimezone
設定に従って常に displayed です。表示する文字列を取得するには(さまざまなタイムゾーンの場合)、入力のタイムゾーンオフセットを保持し、それを使用して出力をフォーマットする必要があります。 (または完全な入力リテラルをtext
として保存します)
最後に、 '2018-04-05 04:00:00 -01' もテストに合格することに注意してください。これは、が正確にであるためです。 timestamptz
値は '2018-04-05 06:00:00 + 01' で、形式が異なります(同じ時点、異なるタイムゾーンで表示)。したがって、3行は、2つだけではなく、例のテストに合格します。
頭が回転している場合は、次のデモを検討してください。
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 <>フィドル ここ