回答:
違いは、日付/時刻型のPostgreSQLドキュメントで説明されています。はい、の治療TIME
またはTIMESTAMP
1との間で異なりますWITH TIME ZONE
かWITHOUT TIME ZONE
。値の保存方法には影響しません。それらの解釈方法に影響します。
これらのデータ型に対するタイムゾーンの影響については、特にドキュメントで説明されています。違いは、システムが値について合理的に知ることができるものから生じます。
値の一部としてタイムゾーンを使用すると、値をクライアントでローカル時間としてレンダリングできます。
値の一部としてタイムゾーンがない場合、明らかにデフォルトのタイムゾーンはUTCであるため、そのタイムゾーンでレンダリングされます。
動作は、少なくとも3つの要因によって異なります。
WITH TIME ZONE
またはWITHOUT TIME ZONE
)。これらの要因の組み合わせをカバーする例を次に示します。
foo=> SET TIMEZONE TO 'Japan';
SET
foo=> SELECT '2011-01-01 00:00:00'::TIMESTAMP;
timestamp
---------------------
2011-01-01 00:00:00
(1 row)
foo=> SELECT '2011-01-01 00:00:00'::TIMESTAMP WITH TIME ZONE;
timestamptz
------------------------
2011-01-01 00:00:00+09
(1 row)
foo=> SELECT '2011-01-01 00:00:00+03'::TIMESTAMP;
timestamp
---------------------
2011-01-01 00:00:00
(1 row)
foo=> SELECT '2011-01-01 00:00:00+03'::TIMESTAMP WITH TIME ZONE;
timestamptz
------------------------
2011-01-01 06:00:00+09
(1 row)
foo=> SET TIMEZONE TO 'Australia/Melbourne';
SET
foo=> SELECT '2011-01-01 00:00:00'::TIMESTAMP;
timestamp
---------------------
2011-01-01 00:00:00
(1 row)
foo=> SELECT '2011-01-01 00:00:00'::TIMESTAMP WITH TIME ZONE;
timestamptz
------------------------
2011-01-01 00:00:00+11
(1 row)
foo=> SELECT '2011-01-01 00:00:00+03'::TIMESTAMP;
timestamp
---------------------
2011-01-01 00:00:00
(1 row)
foo=> SELECT '2011-01-01 00:00:00+03'::TIMESTAMP WITH TIME ZONE;
timestamptz
------------------------
2011-01-01 08:00:00+11
(1 row)
timestamp with time zone
とtimestamp without time zone
、Postgresのではない*ない実際のタイムゾーン情報を格納します。これは、データタイプのドキュメントページで一目で確認できます。どちらのタイプも同じ数のオクテットを使用し、値の保存範囲があるため、タイムゾーン情報を保存するスペースがありません。ページのテキストはこれを確認します。誤解の一部:「tzなし」は「データ挿入時にオフセットを無視する」を意味し、「tz付き」は「オフセットを使用してUTCに調整する」ことを意味します。
参照しているPostgreSQLのドキュメントよりもわかりやすく説明するようにしています。
どちらのTIMESTAMP
バリアントも、名前が示すとおり、タイムゾーン(またはオフセット)を保存しません。違いは、格納形式自体ではなく、格納されたデータの解釈(および目的のアプリケーション)にあります。
TIMESTAMP WITHOUT TIME ZONE
ローカルの日付時刻(別名、壁掛けカレンダーの日付と壁掛け時計の時刻)を格納します。PostgreSQLが認識できる限り、そのタイムゾーンは指定されていません(アプリケーションがそれを知っている場合もあります)。したがって、PostgreSQLは入力または出力でタイムゾーン関連の変換を行いません。値がとしてデータベースに入力された場合、'2011-07-01 06:30:30'
後で表示するタイムゾーンには何も表示されず、2011年、07日、01日、06時間、30分、30秒(ある形式)と表示されます。また、任意のオフセットまたはあなたが入力で指定した時間帯は、PostgreSQLによって無視され、そう'2011-07-01 06:30:30+00'
と'2011-07-01 06:30:30+05'
ばかり同じです'2011-07-01 06:30:30'
。Java開発者の場合:に似ていjava.time.LocalDateTime
ます。
TIMESTAMP WITH TIME ZONE
UTCタイムライン上のポイントを保存します。見た目(時間、分など)はタイムゾーンによって異なりますが、常に同じ「物理的な」瞬間(実際の物理的なイベントの瞬間など)を指します。入力は内部でUTCに変換され、それが格納されます。そのため、入力のオフセットは既知である必要があるため、入力に明示的なオフセットまたはタイムゾーン(など'2011-07-01 06:30:30'
)が含まれていない場合、PostgreSQLセッションの現在のタイムゾーンであると想定されます。それ以外の場合、明示的に指定されたオフセットまたはタイムゾーンが使用されます。 (のように'2011-07-01 06:30:30+05'
)。出力は、PostgreSQLセッションの現在のタイムゾーンに変換されて表示されます。Java開発者の場合:これはjava.time.Instant
(解像度は低くなりますが)に似ていますが、JDBCおよびJPA 2.2では、それをjava.time.OffsetDateTime
(java.util.Date
またはjava.sql.Timestamp
もちろん)。
両方のTIMESTAMP
バリエーションがUTC日時を格納すると言う人もいます。ちょっと、でも私の意見ではそのように言うのは紛らわしいです。TIMESTAMP WITHOUT TIME ZONE
はのように格納さTIMESTAMP WITH TIME ZONE
れ、UTCタイムゾーンでレンダリングされ、たまたまローカルの日付時刻と同じ年、月、日、時間、分、秒、マイクロ秒が与えられます。しかし、それはUTC解釈が言うタイムライン上のポイントを表すことを意味するのではなく、それはローカルの日時フィールドがエンコードされる方法にすぎません。(リアルタイムゾーンはUTCではないため、タイムライン上のドットのクラスターです。それが何であるかはわかりません。)
TIMESTAMP WITH TIME ZONE
として取得しても問題はありませんInstant
。どちらもUTCのタイムライン上のポイントを表します。より自己文書化されているためInstant
、私の意見では、OffsetDateTime
A が優先されTIMESTAMP WITH TIME ZONE
ます。A は常にデータベースからUTCとして取得され、Instant
は常にUTCであるため自然な一致ですが、OffsetDateTime
は他のオフセットを運ぶことができます。
OffsetDateTime
、マッピングされたJava型としてのみ言及しています。Instance
まだどこかで非公式にサポートされているかどうかはわかりません。
'2011-07-01 06:30:30+00'
と'2011-07-01 06:30:30+05'
無視されますが、私はやることができるよinsert into test_table (date) values ('2018-03-24T00:00:00-05:00'::timestamptz);
、それは正しくUTCに変換します。ここで、日付はタイムゾーンなしのタイムスタンプです。タイムゾーン付きのタイムスタンプの主な値が何であるかを理解しようとしていますが、問題があります。
::timestamptz
ます。これで、文字列をTIMESTAMP WITH TIME ZONE
に変換しWITHOUT TIME ZONE
、さらにに変換すると、セッションタイムゾーン(UTC)から見た、その瞬間の「ウォールカレンダー」の日とウォールクロック時間が格納されます。それでも、オフセットが指定されていないローカルタイムスタンプのみになります(ゾーンなし)。
これは役立つはずの例です。タイムゾーンを持つタイムスタンプがある場合、そのタイムスタンプを他のタイムゾーンに変換できます。基本のタイムゾーンがない場合、正しく変換されません。
SELECT now(),
now()::timestamp,
now() AT TIME ZONE 'CST',
now()::timestamp AT TIME ZONE 'CST'
出力:
-[ RECORD 1 ]---------------------------
now | 2018-09-15 17:01:36.399357+03
now | 2018-09-15 17:01:36.399357
timezone | 2018-09-15 08:01:36.399357
timezone | 2018-09-16 02:01:36.399357+03
timestamp
をtimestamptz
意味し、理解する必要があります。timestamptz
絶対時刻(UTC)をtimestamp
意味しますが、特定のタイムゾーンで時計が何を示したかを示します。したがって、timestamptz
タイムゾーンに変換するときに、この絶対的な時点でニューヨークの時計が何を示していたのでしょうか。一方、を「変換」するとき、ニューヨークの時計がxを示した絶対的な時点は何だったのかとtimestamp
尋ねています。
AT TIME ZONE
構築物は、すでに理解していても、独自のティーザー脳であるWITH
対のWITHOUT TIME ZONE
タイプを。したがって、それらを説明するための好奇心の強い選択です。(:(タイムスタンプをタイムスタンプに、またはその逆にAT TIME ZONE
変換します...正確には明らかではありません。)WITH TIME ZONE
WITHOUT TIME ZONE
now()::timestamp AT TIME ZONE 'CST'
ゾーン 'CST'のクロックが、ローカルクロックが現在表示している時間をいつ表示するかを除いて、意味がありません