web-dev-qa-db-ja.com

PostgreSQLのタイムスタンプにタイムゾーンを追加(このタイムゾーンに変換しない)

タイプVARCHAR(タイムゾーンを含む、たとえば「ヨーロッパ/ローマ」)、DATEおよびINTERVALの3つの個別のフィールドがあります。そして、それらをクエリで組み合わせて、TIMESTAMP WITH TIME ZONE。この値を作成するルールは次のとおりです。

指定されたタイムゾーンで指定された日付の正午、マイナス12時間、プラス指定された間隔(この-12時間は、DSTを処理するために必要です)。

明らかにINTERVALの加算/減算は問題ではありません。私の問題は、「指定されたタイムゾーンの指定された日付の正午」を作成する方法が理解できないことです。

簡単な例:

  • タイムゾーンフィールド「ヨーロッパ/ローマ」がある場合
  • 日付は2018-03-24(このタイムゾーンのDST切り替えの日付)
  • 間隔は「1時間」です

計算は次のようになります。

  1. 指定された日付の正午を作成:2018-03-24 12:00:00 'ヨーロッパ/ローマ'タイムゾーン
  2. 減算INTERVAL '12 hours'、結果は2018-03-24 01:00:00 at 'Europe/Rome' time zone(DSTのため)
  3. 追加 INTERVAL '1 hour'、最終結果は2018-03-24 02:00:00 at 'Europe/Rome' time zoneです。

ポイント1の方法を教えてください。

追伸データのスキーマを変更できません。 [〜#〜] gtfs [〜#〜] postgresにロードされるデータから取得されます。要するに、このスキーマの特徴は、タイムゾーン、日付、時間間隔を3つの異なるテーブルに保存することです agencycalendar_dates および stop_times ( 、タイムゾーンは別の表にある場合がありますが、この質問では重要ではありません)。

5
Fly

あなたの例は構文的に正しいわけではありませんが、問題はPostgreSQLが日付を含む文字列リテラルをtimestamp with time zoneとして解釈することです。

ただし、逆の方法をとる必要があります。正午にtimestamp without timezoneを使用し、次にAT TIME ZONE 'Europe/Rome'を使用して、「正午のままの絶対時刻」(PostgreSQLではtimestamp with time zoneと呼ばれる)を含む絶対タイムスタンプを取得します。ローマ」、時間を追加します。

表示される結果は、セッションのタイムゾーンによって異なります。

同じ結果が得られるようにUTCを使用して、上記をSQLで記述します。

SET timezone=UTC;

SELECT '2018-03-24 12:00:00'::timestamp without time zone
   AT TIME ZONE 'Europe/Rome'
   + INTERVAL '1 hour';

        ?column?        
------------------------
 2018-03-24 12:00:00+00
(1 row)
2
Laurenz Albe