sql >> データベース >  >> RDS >> PostgreSQL

PostgreSQLでTIMEWITHTIMEZONEを適切に処理する

    あなたは次のように主張しました:

    だからあなたは決して 同じ行内の日付行を横切ります。 1x日付を保存することをお勧めします 3倍の時間 およびタイムゾーン text として またはFK列):

    CREATE TABLE legacy_table (
       event_id      bigint PRIMARY KEY NOT NULL
     , report_date   date NOT NULL
     , start_hour    time
     , end_hour      time
     , expected_hour time
     , tz            text  -- time zone
    );
    

    すでに見つけたように、 timetz タイムゾーンのある時間 )通常は避ける必要があります 。 DSTルールを適切に処理できません( d aylight s t ime)。

    つまり、基本的にはすでに持っていたもの start_hourから日付コンポーネントを削除するだけです 、それは死んだ貨物です。 タイムスタンプをキャストします time 日付を切り落とす。例:(timestamp '2018-03-25 1:00:00')::time

    tz ATで受け入れられる任意の文字列にすることができますタイムゾーン 構築しますが、異なるタイムゾーンを確実に処理するには、タイムゾーン名を排他的に使用するのが最善です。任意のname システムカタログpg_timezone_names>

    ストレージを最適化するために、許可されたタイムゾーン名を小さなルックアップテーブルに収集し、 tz textを置き換えることができます。 tz_id int REFERENCES my_tz_tableを使用 。

    DSTがある場合とない場合の2つの行の例:

    INSERT INTO legacy_table VALUES
       (1, '2018-03-25', '1:00', '3:00', '2:00', 'Europe/Vienna')  -- sadly, with DST
     , (2, '2018-03-25', '1:00', '3:00', '2:00', 'Europe/Moscow'); -- Russians got rid of DST
    

    表現の目的または計算のために、次のようなことができます。

    SELECT (report_date + start_hour)    AT TIME ZONE tz AT TIME ZONE 'UTC' AS start_utc
         , (report_date + end_hour)      AT TIME ZONE tz AT TIME ZONE 'UTC' AS end_utc
         , (report_date + expected_hour) AT TIME ZONE tz AT TIME ZONE 'UTC' AS expected_utc
         -- START_HOUR - END_HOUR
         , (report_date + start_hour) AT TIME ZONE tz
         - (report_date + end_hour)   AT TIME ZONE tz AS start_minus_end
    FROM   legacy_table;
    

    1つ以上のビュー を作成できます。 必要に応じて文字列を簡単に表示できます。このテーブルは、必要な情報を保存するためのものです。 。

    括弧に注意してください!それ以外の場合、演算子 + AT TIME ZONEの前にバインドします 演算子の優先順位 による 。

    そして結果を見てください:

    db <> fiddle こちら

    ウィーンでは時間が操作されるため(愚かなDST規則が適用される場所と同様)、「驚くべき」結果が得られます。

    関連:




    1. インデックス内の列の位置

    2. MySQLは日付に日を追加します

    3. SQLServerテーブルからn個のランダムな行を選択します

    4. クエリのパフォーマンスの違いpl/sqlforallinsertとplainSQLinsert