データ型がtimestamptz
のテーブル列があります。サーバーのタイムゾーンはAmerica/Denverです。その列に値を挿入するときに、奇妙な問題が発生します。
列を値'03/11/2018 02:00:00'
に更新すると、'03/11/2018 03:00:00'
(+ 1時間!)になります。
UPDATE details
SET interval_start_timestamp = '03/11/2018 02:00:00'::TIMESTAMP
WHERE id = 2395
問題は、時刻が02:00:00の場合のみです。 02:30:00および01:00:00や01:30:00などの他の値は適切に挿入されます。
Gccでコンパイルされたx86_64-pc-linux-gnu上のPostgreSQL 9.5.7(Ubuntu 4.8.4-2ubuntu1〜14.04.3)4.8.4、64ビット
誰かがこの動作を理解するのを助けることができますか?
そして、どのようにして適切な値を挿入できますか?
あなたは悪いアイデアのカスケードの犠牲になった。
DateStyle
回避できる場合は、ステートメントでロケール依存形式を使用しないでください。ロケール設定が変更された場合( lc_time
および DateStyle
特に)、ステートメントが突然別のことを行います。 '03/11/2018'
は、特定の設定と組み合わせない限りあいまいです。常に ISO形式 を使用します。これは明確であり、追加の設定に依存しません:'2018-03-11'
。
timezone
timestamp
値(またはリテラル)をtimestamptz
列に割り当てないでください。割り当てキャストは、別の依存関係を導入するセッションの現在のtimezone
設定に依存します。タイムゾーン設定が異なると、ステートメントの動作が異なります。明示的なキャストまたはtimestamp with time zone
リテラル(timestamptz
)。あなたの場合:
UPDATE details
SET interval_start_timestamp = '2018-03-11 02:00:00'::timestamp AT TIME ZONE 'America/Denver'
WHERE id = 2395
実際のタイムゾーンnameを使用すると(省略形ではありません)、DSTが確実に考慮されます-OSがPostgresが基盤となるOSによって提供される情報を処理するため、最新の状態。
関連:
結果は'2018-03-11 03:00:00'
。 ypercubeが指摘した のように、 start ofSummer TimeakaDaylight Savings Time 。この時、時計は1時間進みました。 02:00:00と02:59:59.999999の間の各時間は、DSTの愚かな規則によって、それぞれ03:00:00または03:59:59.999999の間の何かを意味すると解釈されます。
「夏時間」(DST)の単なる存在は、理由に対する侮辱です。それは廃止され、二度と話されるべきではありません(これを永遠に混乱させる運命にある運命の時間の値を除いて)。
テスト:
SELECT '2018-03-11 02:34:00'::timestamp AT TIME ZONE 'America/Denver' AT TIME ZONE 'America/Denver' AS t2 , '2018-03-11 03:34:00'::timestamp AT TIME ZONE 'America/Denver' AT TIME ZONE 'America/Denver' AS t3;
t2 | t3 :------------------ | :------------------ 2018-03-11 03:34:00 | 2018-03-11 03:34:00
dbfiddle ここ