あなたは次のように主張しました:
だからあなたは決して 同じ行内の日付行を横切ります。 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規則が適用される場所と同様)、「驚くべき」結果が得られます。
関連: