web-dev-qa-db-ja.com

timestamptz列の値を更新する

データ型が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ビット

誰かがこの動作を理解するのを助けることができますか?
そして、どのようにして適切な値を挿入できますか?

2
Harshal Mahajan

あなたは悪いアイデアのカスケードの犠牲になった。

1. DateStyle

回避できる場合は、ステートメントでロケール依存形式を使用しないでください。ロケール設定が変更された場合( lc_time および DateStyle 特に)、ステートメントが突然別のことを行います。 '03/11/2018'は、特定の設定と組み合わせない限りあいまいです。常に ISO形式 を使用します。これは明確であり、追加の設定に依存しません:'2018-03-11'

2. 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によって提供される情報を処理するため、最新の状態。

関連:

3. DST

結果は'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 ここ

3