web-dev-qa-db-ja.com

AT TIME ZONEおよびUTCオフセットの奇妙さ

これら2つの列の違いがわかりません。アメリカ/シカゴのタイムゾーンはUTC-6なので、どちらも同じ結果を返すと思います。

select timezone('America/Chicago', '2017-01-01 12:00:00'::TIMESTAMP AT TIME ZONE 'UTC'),
       timezone('UTC-6'          , '2017-01-01 12:00:00'::TIMESTAMP AT TIME ZONE 'UTC');

ただし、結果は次のとおりです。

2017-01-01 06:00:00 | 2017-01-01 18:00:00

また、この動作は非常に厄介です。

SELECT '1:00 -1'::time with time zone AT TIME ZONE '-1'; 
  timezone   
-------------
 03:00:00+01

誰かがこれを説明できますか?

6
Asaf David

タイムゾーンnameは、省略形よりも多くの情報を運びますまたは単純なタイムゾーンoffset 'UTC-6'は「POSIXスタイルのタイムゾーン指定」であり、これは略語にオフセットを加えたものです。
タイムゾーンのマニュアル

PostgreSQLでは、3つの異なる形式でタイムゾーンを指定できます。

  • 完全なタイムゾーン名。たとえば、_America/New_York_。 [...]

  • タイムゾーンの省略形、たとえばPST。 [...]

  • タイムゾーン名と省略形に加えて、PostgreSQLはSTDoffsetまたはSTDoffsetDST、ここでSTDはゾーンの省略形、オフセットは数値offsetUTCから西の時間で、DSTはオプションの夏時間ゾーンの省略形で、指定されたオフセットより1時間進んでいると想定されています。

あなたが観察する違いは別の奇妙さから生じます。 _+_ の代わりに _-_ を使用する必要があります:

timezone('UTC+6', '2017-01-01 12:00:00'::TIMESTAMP AT TIME ZONE 'UTC')

再びマニュアル:

覚えておくべきもう1つの問題は、POSIXタイムゾーン名では、グリニッジの west の場所に正のオフセットが使用されることです。それ以外の場所では、PostgreSQLは正のタイムゾーンオフセットがグリニッジの east であるというISO-8601規則に従います。

ただし、オフセットエラーを修正した後でも、両方の式はと同等ではありません。特に、 'America/Chicago'のようなタイムゾーン名は、夏時間(DST)のルールも考慮します。

ところで、式は次のように簡略化できます。

_timestamptz '2017-01-01 12:00:00 +0' AT TIME ZONE 'UTC+6'
_

しかし、タイムゾーンnameを安全にしたいと思うでしょう:

_timestamptz '2017-01-01 12:00:00 +0' AT TIME ZONE 'America/Chicago'
_

関連:


2番目の例に対応するには

_SELECT '1:00 -1'::time with time zone AT TIME ZONE '-1';
_

簡略化された同等の構文:

_SELECT timetz '1:00 -1' AT TIME ZONE '-1';
_

リテラル_-1_の2つのインスタンスには、異なる意味があります。最初のオフセットは、グリニッジの場所eastを示す_*timetz*_リテラルの一部です(SQL標準に準拠)。 2番目は、POSIXスタイルのタイムゾーン指定で、オフセットwestグリニッジ。ゾーン指定がない場合は、UTCがベースとして想定されます。見る:

_AT TIME ZONE_構文 は、timetz入力に対してtimetzを返すことにも注意してください。時間リテラルを別のオフセットに再配置するだけです。これは、データタイプも切り替えられるtimestamp/timestamptz入力での使用とは異なります。

ただし、データ型timetz(_time with time zone_)は使用しないでください。標準SQLの一部であるため、設計上は機能せず、Postgresにのみ含まれています。使用は明示的にお勧めしません。見る:

10