2つの例を説明しましょう:
どちらの場合も、タイムゾーンUTC(つまり、SET timezone TO UTC
)を想定しています。 。
db=# SELECT timezone('US/Pacific', '2016-01-01 00:00');
timezone
---------------------
2015-12-31 16:00:00
(1 row)
これは、SELECT timezone('US/Pacific', '2016-01-01 00:00'::timestamptz)
と同等です。 つまり、Postgresは文字列を暗黙的にtimestamptz
に変換しました 。
timezone
関数はtimestamp
間を行ったり来たりします およびtimestamptz
:
timestamptz
を指定しているので 入力として、timestamp
を出力します 。つまり、絶対時点2016-01-01 00:00Z
を変換しています。 US/Pacific
の実時間まで 、つまり、ロサンゼルスの時計がその絶対的な時点で示したものです。
例2では、逆のことを行っています。つまり、timestamp
を取得しています。 そしてそれをtimestamptz
に変換します 。言い換えれば、私たちは尋ねています:ロサンゼルスの時計が2016-01-01 00:00
を示した絶対的な時点は何でしたか ?
あなたが言及する:
'2016-01-01 00:00'::timestamp
timestamp
です 、つまり壁時計。タイムゾーンの概念はありません。
timestamp
の違いを完全には理解していないかもしれません およびtimestamptz
、ここで重要なのは。それらを実時間と考えてください。 、つまり、壁に掛かっている時計で世界のどこかに表示された時間、および絶対時間 、つまり私たちの宇宙の絶対時間。
あなたがあなた自身の答えで作る例は完全に正確ではありません。
SELECT ts FROM (VALUES
(timestamptz '2012-03-05 17:00:00+0') -- outputs 2012-03-05 17:00:00+00 --1
,(timestamptz '2012-03-05 18:00:00+1') -- outputs 2012-03-05 17:00:00+00 --2
,(timestamp '2012-03-05 18:00:00+1') -- outputs 2012-03-05 18:00:00+00 --3
,(timestamp '2012-03-05 11:00:00' AT TIME ZONE '+6') -- outputs 2012-03-05 17:00:00+00 --4
,(timestamp '2012-03-05 17:00:00' AT TIME ZONE 'UTC') -- outputs 2012-03-05 17:00:00+00 --5
,(timestamp '2012-03-05 17:00:00'::timestamp) -- outputs 2012-03-05 17:00:00+00 --6
,(timestamp '2012-03-05 17:00:00'::timestamptz) -- outputs 2012-03-05 17:00:00+00 --7
) t(ts);
あなたの例の問題は、単一の列で1つのデータセットを構築していることです。列は1つのタイプしか持てないため、各行(この場合は単一の値)は同じタイプ、つまりtimestamptz
に変換されます。 、一部の値はtimestamp
として計算されましたが (例:値3)。したがって、ここに追加の暗黙的な変換があります。
例を個別のクエリに分割して、何が起こっているかを見てみましょう:
例1
db=# SELECT timestamptz '2012-03-05 17:00:00+0';
timestamptz
------------------------
2012-03-05 17:00:00+00
ご存知かもしれませんが、timestamptz '2012-03-05 17:00:00+0'
および'2012-03-05 17:00:00+0'::timestamptz
同等です(私は後者を好みます)。したがって、記事と同じ構文を使用するために、次のように書き直します。
db=# SELECT '2012-03-05 17:00:00+0'::timestamptz;
timestamptz
------------------------
2012-03-05 17:00:00+00
さて、ここで何が起こっているのですか?まあ、あなたの元の説明よりも少ないです。文字列は単純にtimestamptz
として解析されます 。結果が出力されると、現在設定されているtimezone
が使用されます。 基になるデータ構造の人間が読める表現に変換するように構成します。つまり、2012-03-05 17:00:00+00
。
timezone
を変更しましょう 設定して何が起こるかを確認します:
db=# SET timezone TO 'Europe/Berlin';
SET
db=# SELECT '2012-03-05 17:00:00+0'::timestamptz;
timestamptz
------------------------
2012-03-05 18:00:00+01
変更されたのは方法だけです timestamptz
画面に印刷されます。つまり、ヨーロッパ/ベルリンを使用します。 タイムゾーン。
例2
db=# SELECT timestamptz '2012-03-05 18:00:00+1';
timestamptz
------------------------
2012-03-05 17:00:00+00
(1 row)
繰り返しますが、日付を解析するだけです。
例3
db=# SELECT timestamp '2012-03-05 18:00:00+1';
timestamp
---------------------
2012-03-05 18:00:00
(1 row)
これは、'2012-03-05 18:00:00+1'::timestamp
と同じです。 。ここで何が起こるかというと、timestamp
を要求しているため、タイムゾーンオフセットは単に無視されます。 。
例4
db=# SELECT timestamp '2012-03-05 11:00:00' AT TIME ZONE '+6';
timezone
------------------------
2012-03-05 17:00:00+00
(1 row)
簡単に書き直してみましょう:
db=# SELECT timezone('+6', '2012-03-05 11:00:00'::timestamp);
timezone
------------------------
2012-03-05 17:00:00+00
(1 row)
これは質問です:+6時間のオフセットがあるタイムゾーンの壁の時計が2012-03-05 11:00:00
を示していた絶対時間は何でしたか ?
例5
db=# SELECT timestamp '2012-03-05 17:00:00' AT TIME ZONE 'UTC';
timezone
------------------------
2012-03-05 17:00:00+00
(1 row)
書き直してみましょう:
db=# SELECT timezone('UTC', '2012-03-05 17:00:00'::timestamp);
timezone
------------------------
2012-03-05 17:00:00+00
(1 row)
これは質問です:タイムゾーンUTCの壁の時計が2012-03-05 17:00:00
を示していた絶対時間は何でしたか ?
例6
db=# SELECT timestamp '2012-03-05 17:00:00'::timestamp;
timestamp
---------------------
2012-03-05 17:00:00
(1 row)
ここでは、timestamp
に2回キャストしています 、違いはありません。簡単にしましょう:
db=# SELECT '2012-03-05 17:00:00'::timestamp;
timestamp
---------------------
2012-03-05 17:00:00
(1 row)
それは明らかだと思います。
例7
db=# SELECT timestamp '2012-03-05 17:00:00'::timestamptz;
timestamptz
------------------------
2012-03-05 17:00:00+00
(1 row)
書き直してみましょう:
db=# SELECT ('2012-03-05 17:00:00'::timestamp)::timestamptz;
timestamptz
------------------------
2012-03-05 17:00:00+00
(1 row)
最初に文字列をtimestamp
として解析します そしてそれをtimestamptz
に変換します 現在設定されているtimezone
を使用する 。 timezone
を変更した場合 、Postgresはtimestamp
を変換するときにそのタイムゾーンを想定しているため、別のものが得られます (またはタイムゾーン情報が不足している文字列)からtimestamptz
:
db=# SET timezone TO 'Europe/Berlin';
SET
db=# SELECT ('2012-03-05 17:00:00'::timestamp)::timestamptz;
timestamptz
------------------------
2012-03-05 17:00:00+01
(1 row)
UTCで表されるこの絶対時間は、2012-03-05 16:00:00+00
です。 、したがって、元の例とは異なります。
これが物事を明らかにすることを願っています。繰り返しますが、timestamp
の違いを理解する およびtimestamptz
キーです。実時間と絶対時間の違いを考えてください。