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 キーです。実時間と絶対時間の違いを考えてください。