両者の違いについては、長くて明確な答えがあります
TIMESTAMP WITH TIME ZONE
-vs-TIMESTAMP WITHOUT TIME ZONE
SO postRails and PostgreSQL)でタイムゾーンを完全に無視する。
私が知りたいのは、実際にTIMESTAMP WITHOUT TIME ZONE
を使用する有効な使用例はありますか、それともアンチパターンと見なす必要がありますか?
これは多くの場所で述べられていますが、timestamp with time zone
をtimestamp without time zone
タイプと比較するときは常に言及する価値があると思います:timestamp WITH time zone
はタイムゾーンを保存しません情報とタイムスタンプ。すべてのデータをUTCタイムゾーンで保存することです ドキュメントに記載されています :
タイムゾーン付きのタイムスタンプの場合、内部的に保存される値は常にUTC(協定世界時、グリニッジ標準時、GMTとして知られています)です。明示的なタイムゾーンが指定されている入力値は、そのタイムゾーンの適切なオフセットを使用してUTCに変換されます。入力文字列にタイムゾーンが指定されていない場合は、システムのTimeZoneパラメータで指定されたタイムゾーンであると見なされ、タイムゾーンゾーンのオフセットを使用してUTCに変換されます。
(1)すべてが同じタイムゾーンにある場合、または(2)アプリケーション層がタイムゾーンを処理し、すべてを特定のタイムゾーン(通常はUTC)に格納する場合に、一部がtimestamp WITHOUT time zone
を使用することは有効と見なされます。しかし、(1)の正しい解決策はTimeZone設定をシステムの指定された1つのタイムゾーンに設定することであり、(2)PostgreSQLはすでにすべてを同じタイムゾーンに格納しているため、すでに解決されているため、アンチパターンとも見なされます。 (UTC)。
さて、これら2つがダウンしたので、timestamp WITHOUT time zone
を使用する正当な理由が1つだけあります。これは、将来のイベントを保存したいときであり、その時間に達したときに何らかのアラートをトリガーする必要があります。これは、タイムゾーンに関する地域の法律によって定義されたルールが変更されない場合にのみ、timestamp WITH time zone
に適しています。変更の最も一般的なルールは、夏時間(DST)の採用または不採用についてです。
たとえば、2013-06-15
(まだDSTにない)で2013-01-15 10:00
(既にDSTにある)でイベントが発生するようにスケジュールしていて、2013-06-15
で地域がDSTを採用するように指定されているとします。しかし、その後しばらくして、政府はルールを変更し、地域がDSTを使用しなくなると言い、予定時刻が(2013-01-15 11:00
ではなく)10:00
になり、timestamp WITH time zone
を使用し、TZ構成を最新に保つ場合日付。もちろん、関心のあるリージョン/タイムゾーンでのルールの変更を追跡し、影響を受けるレコードを更新すれば、そのようなケースをタイムゾーンでも処理できることに気付くかもしれません。
一部の地域ではこれらのルールが頻繁に変更されることを言及する価値があります(ブラジルでは、国全体ではなく一部の州が変更されることが多いなど)が、ほとんどの場合それは非常に早く変更されるため、ユーザーは非常に遠くにスケジュールされたイベントによってのみ影響を受けます現在の時刻。
以上のことから、提案はもう1つだけあります。ユーザー、ログ、または何かが異なるタイムゾーンにある場合は、どこかからのタイムゾーンを保存し、timestamp with time zone
を選択して使用します。これにより、(1)異なるソース(タイムゾーンに関係なく)で互いにより近く発生するイベントをクロスし、(2)イベントが発生した元の時間(クロック時間)を表示できます。
はい。TIMESTAMP WITHOUT TIME ZONE
の使用例があります。
WITHOUT
ではなくTIMESTAMP WITH TIME ZONE
を使用します。TIMESTAMP WITHOUT TIME ZONE
の値は、タイムライン上のnotポイントではなく、not実際の瞬間です。それらは、潜在的なモーメント、約26〜27時間の範囲(世界中のタイムゾーンの範囲)に沿ったタイムライン上の可能なポイントについての大まかなアイデアを表しています。 time zone または offset-from-UTC を適用するまで、これらは実際の意味を持ちません。
たとえば、休日/聖日の開始を記録する必要があるとします。
Table: holiday_
Column: year_ Type: SMALLINT
Column: description_ Type: VARCHAR
Column: start_ Type: TIMESTAMP WITHOUT TIME ZONE
今年の12月25日の真夜中にクリスマスが始まるという事実を記録するには、タイムゾーンなしで2016-12-25 00:00:00
と言う必要があります。サンタの日の早い時間に、彼は真夜中の直後にオークランドNZを訪れます。これは、世界で最も早い真夜中の1つであるためです。それから彼は西に向かって働き、次の真夜中に起こり、すぐにフィリピンに到着します。その後、トナカイは西に進み、真夜中にインドに到着します。これは、オークランドの真夜中から数時間後に起こります。それよりずっと後は、パリFRで真夜中、カリフォルニア州モントリオールでまだ真夜中です。サンタによるこれらすべての訪問は異なる瞬間が時間で発生しますが、すべての深夜の直後に、各地域の深夜ごとに発生しました。
したがって、クリスマスの始まりとしてタイムゾーンなしで2016-12-25 00:00:00
を録音することは有益で合法的ですが、漠然としたものです。 「オークランドのクリスマス」または「モントリオールのクリスマス」と言うまで、特定の瞬間はありません。そりが接地するたびに実際の瞬間を記録する場合は、WITHOUT
タイプではなくTIMESTAMP WITH TIME ZONE
を使用します。
クリスマスに似ているのは大晦日です。 ニューヨークでタイムズスクエアボールが落ちる のとき、シアトルの人々はシャンパンを冷やして パーティーホーン を準備しています。それでも、新年の瞬間のideaを2017-01-01 00:00:00
としてTIMESTAMP WITHOUT TIME ZONE
に記録します。対照的に、ボールがニューヨークで落ちたとき、またはシアトルの人々が角を吹き飛ばしたときを記録したい場合は、代わりにTIMESTAMP WITH TIME ZONE
(WITHOUT
ではなく)を使用して実際の瞬間を記録します。それぞれ3時間離れています。
別の例として、さまざまな場所で 壁時計時間 を含むポリシーを記録する場合があります。デトロイト、デュッセルドルフ、デリーに工場があるとします。 3つの工場すべてで、最初のシフトが午前6時に始まり、昼休みが午前11時30分になるとすると、これはTIMESTAMP WITHOUT TIME ZONE
として記録できます。繰り返しますが、この情報はあいまいな形で役立ちますが、タイムゾーンを適用するまで特定の瞬間を示すものではありません。新しい日が東の早い時期に明けます。そのため、デリーの工場は午前6時に最初にオープンする予定です。数時間後、デュッセルドルフの工場は午前6時に作業を開始します。しかし、デトロイトの工場は実際には6時間後の午前6時まで開かれません。
この考え(工場のシフトが一般的にいつ始まるか)を、各工場労働者が特定の日にシフトを開始するために出社したときの歴史的事実と比較してください。出勤は実際の瞬間であり、タイムライン上の実際のポイントです。したがって、WITHOUT
タイプではなく、タイプTIMESTAMP WITH TIME ZONE
の列にそれを記録します。
そのため、はい、TIMESTAMP WITHOUT TIME ZONE
には正当なユースケースがあります。しかし、私のビジネスアプリの経験では、それらは比較的まれです。ビジネスでは、実際の瞬間に注意を払う傾向があります。請求書が実際に到着したのはいつですか、正確にその契約が有効になるのはいつですか、その銀行取引はいつ実行されましたか。したがって、このような一般的な状況では、TIMESTAMP WITH TIME ZONE
タイプが必要です。
詳細については、同様の質問の my Answer を参照してください シフト用にUTCタイムスタンプまたはローカル時間を保存する必要があります
Postgresは特にneverは、タイムスタンプを挿入するときに指定されたタイムゾーン情報を保存しないことに注意してください。
TIMESTAMP WITH TIME ZONE
TIMESTAMP WITH TIME ZONE
をTIMESTAMP WITH RESPECT FOR TIME ZONE
と考えてください。TIMESTAMP WITHOUT TIME ZONE
SQL標準では、日時データ型と動作の問題にはほとんど触れていません。そのため、データベースは日時の処理において大きく異なります。
これに別の見方を追加したいと思います。これは、他の回答に書かれていることの多くに反します。私の考えでは timestamp with time zone
には有効なユースケースがほとんどなく、timestamp without time zone
が一般的に推奨されます。
まず、「UTC everywhere」パターンを理解する必要があります。これは、特別な要件がないすべてのアプリケーションに一般的に推奨されるパターンです。これは単に、アプリケーションがすべてのタイムスタンプをいつでもどこでもUTCで表す必要があることを意味します。もちろん、ローカルの日付/時刻をユーザーに表示しますが、ビューをレンダリングするときに、プログラムのまさにエッジでこれらを変換するのが目的です。これは、UTCタイムスタンプ(データベースからロードした可能性がある)とユーザーのタイムゾーン(ブラウザから取得した可能性がある)をローカルタイムスタンプに結合するのに適切な場所です。
このパターンに従っている場合、timestamp with time zone
はアンチパターンです。このタイプが行うことはすべて、PostgreSQLのTimeZone
セッション変数に基づいて、タイムスタンプを読み書きするときにPostgreSQLにタイムゾーン変換を実行させることです。アプリケーションの最端でタイムゾーンを処理する代わりに、タイムゾーンを心臓部に、データベースとの通信に導入しました。 PostgreSQL TimeZone
を常に適切に構成し、不必要な障害や混乱のポイントを追加するように注意する必要があります。
そして何のために? UTC everywhereパターンに従っている場合、アプリケーションにはとにかくUTCタイムスタンプしかありません。では、なぜデータベースにタイムゾーンの変換を依頼するのでしょうか。単にtimestamp without time zone
カラム、そして常にUTCであるかのように扱います。変換、タイムゾーン、複雑化はありません。
date
タイムスタンプにもタイムゾーン情報は含まれていませんが、多くの人がタイムゾーン情報を使用しています。
もちろん、それ自体は答えではありません。
常に同じタイムゾーンにあるか、既知のタイムゾーンに関連して保存されているタイムスタンプと日付には、timestamp
とdate
を使用することが有効です。
タイムゾーンが常に同じであるか暗黙的である場合は、タイムゾーンを格納しないよりも格納する方がアンチパターンになります(冗長な情報)。
タイムスタンプは、アプリケーションログで使用されるような技術情報の保存やパフォーマンス測定にも使用できます。この場合、タイムゾーンも重要ではありません。
逆に、システムの一部が異なるタイムゾーンに分散される分散システムまたはシステムで設計または作業している場合、timestamp with timezone
を使用しないことはアンチパターンと見なされる場合がありますが、一部のシステムUTCなどの1つのタイムゾーンで実行するように設計されている場合があります。この場合、タイムゾーンロジックがアプリケーション層にプッシュされている可能性がありますが、私はこれをアンチパターンと考えています。
アプリケーションが単一のタイムゾーンに制限されている場合、日付/時刻をローカル時間で保存および処理するのは魅力的ですが、これは間違いだと思います。
夏時間から標準時間に戻すと、現地時間が1時間繰り返されます(時差が1時間であると想定)。私が住んでいる場所では、通常午前2時頃に発生するため、現地時間は01:58、01:59、01:00となり、繰り返される時間の終わりにのみ02:00に進みます。
現地時間を使用して時間順にイベントを並べ替えようとすると、2つの異なる時間のイベントが混ざり合い、実際に発生した順序で表示されません。
比較すると、UTCにはこの問題がなく、きれいに注文できます。したがって、1つのタイムゾーンだけを使用する場合でも、DBで時間をUTCで保存および処理し、入力/表示用にローカル時間との間で変換する必要があります。これは、TIMESTAMP WITH TIME ZONEの動作です。