web-dev-qa-db-ja.com

なぜPostgreSQLは数値UTCオフセットをISO-8601ではなくPOSIXとして解釈するのですか?

タイムゾーンを数値オフセットとして設定すると(abbrevがないため、IMOはPOSIX形式ではありません)、PostgreSQLによってPOSIX形式として解釈されます。

SET TIME ZONE '+02:00';

以下を介してUTFオフセットをチェックするため、少なくとも私は仮定します。

SELECT EXTRACT(TIMEZONE FROM now()) * interval '1sec';

-02:00:00が生成されます。これは、ドキュメントに記載されているように、グリニッジからのオフセットが逆になることを意味します。

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

名前付きタイムゾーンを介して設定すると、UTCからの正のオフセットが生成されます。

SET TIME ZONE 'Europe/Prague'; -- +02:00 DST at time of writing
SELECT EXTRACT(TIMEZONE FROM now()) * interval '1sec'; -- `02:00:00`

Postgres docs は、タイムゾーンを指定する方法が3つあることを示していますが、いずれも+00:00数値構文に言及していません。

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

  • 完全なタイムゾーン名(例:America/New_York)。認識されるタイムゾーン名はpg_timezone_namesビューに一覧表示されます( セクション51.90 を参照)。 PostgreSQLはこの目的のために広く使用されているIANAタイムゾーンデータを使用しているため、同じタイムゾーン名が他の多くのソフトウェアでも認識されます。
  • タイムゾーンの省略形、たとえばPST。このような仕様は、一連の夏時間の移行日の規則も意味する可能性がある完全なタイムゾーン名とは対照的に、UTCからの特定のオフセットを定義するだけです。認識される略語はpg_timezone_abbrevsビューにリストされています( セクション51.89 を参照)。構成パラメーター TimeZone または log_timezone をタイムゾーンの省略形に設定することはできませんが、日付/時刻の入力値およびAT TIME ZONE演算子。
  • タイムゾーン名と省略形に加えて、PostgreSQLはSTDoffsetまたはSTDoffsetDST[...]

しかし、POSIX(上記のポイント3)はどこにも±00:00形式について言及していないため(STD略語が必要な場合のみ)、そのカテゴリには該当しないと思います。

さらに、 docs の他の場所で±00:00ISO 8601として明示的に指定されています。これはTIMESTAMPTZデータ型に適用され、ランタイムtimezone構成には適用されないことを理解していますが、postgresが同じ形式を2つの異なる方法で解釈するのはおかしいようです。

その上、±00:00形式は、ウィキペディアで ISO 8601 として言及されています。

Q1:それで、Postgresは実際に±00:00をPOSIXとして解釈しますか(または何か他のことが起こっています)、なぜですか?

Q2:また、postgresql.confで、または実行時にSET TIME ZONEを介して設定できるフォーマットの明確なリストがありますはPOSIXとして解釈され、どちらがISO-8601として解釈されますか?


(この質問は私の以前の続きです: なぜpostgresqlは名前付きと数値のタイムゾーン表記を区別するのですか? ありがとう jjanes 正しい方向。)


EDIT(18-08-26 18:56)反映するために アーウィンの答え

まず、SET docs状態(リスト番号を追加、強調):

SET TIME ZONE valueSET timezone TO valueのエイリアスです。構文SET TIME ZONEでは、タイムゾーンを指定するための特別な構文を使用できます。有効な値の例を次に示します。

  1. 'PST8PDT'

    カリフォルニア州バークレーのタイムゾーン。

  2. 'Europe/Rome'

    イタリアのタイムゾーン。

  3. -7

    UTCから7時間西のタイムゾーン(PDTに相当)。正の値はUTCの東側です。

  4. INTERVAL '-08:00' HOUR TO MINUTE

    UTCから8時間西のタイムゾーン(PSTに相当)。

[...]

数値または間隔として指定されたタイムゾーン設定は、POSIXタイムゾーン構文に内部的に変換されます。たとえば、SET TIME ZONE -7の後、SHOW TIME ZONEはレポートします<-07>+07

強調された文は間違っているか、不完全であるか、まったく理解できません。

  1. それは、彼らのPOSIX風の文字列(1)が文字列であるため、ISO-8601として解釈されるということですか?それをテストしましょう。

    SET TIME ZONE 'PST8PDT';
    SELECT EXTRACT(TIMEZONE FROM now()) * interval '1sec';
    

    収量-07:00:00、これは負の値であり、負の値はISO-8601でのみグリニッジの西側にあります。これは、 docs state (強調は私のものです):

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

    上記の引用がない限り、タイムスタンプリテラルのみが適用されます。

    そうでない場合、'PST8PDT'文字列は確かにISO-8601として解釈されるようです。

    だが、

    SET TIME ZONE 'UTC2';
    SELECT EXTRACT(TIMEZONE FROM now()) * interval '1sec';
    

    -02:00:00 ..が生成されます。では、再びPOSIXに戻りますか?またはUTC2はPOSIXSTDoffset形式ではありませんか?

  2. 数値形式-7はPOSIXとして解釈されるように指定されているので、もう一度テストしてみましょう。

    SET TIME ZONE 2;
    SELECT EXTRACT(TIMEZONE FROM now()) * interval '1sec';
    

    02:00:00が生成されます。うーん..それは私にとってISO-8601のように聞こえます。 +2時間、グリニッジの東。

  3. '+02:00'はどこに該当しますか?これは数値ではなく、間隔ではありませんが、POSIXオフセットが発生するため、postgresが間隔として解析するかのように動作します。

    SET TIME ZONE '+02:00';
    SELECT EXTRACT(TIMEZONE FROM now()) * interval '1sec';
    

    収量-02:00:00

だから私はまだ混乱しています。頭に浮かぶもう1つの質問:

Q3:グリニッジの西/東のPOSIXのプラス/マイナスの反転は、タイムスタンプリテラルまたはタイムゾーン構成にも適用されますか?

4
dwelle

良い質問です。マニュアルは簡単に読み違える可能性があります。 同じソース を引用していますが、もう1つの先行文があります。

すべてのタイムゾーン対応の日付と時刻は、内部でUTCに格納されます。それらは、クライアントに表示される前に、 TimeZone 構成パラメーターで指定されたゾーンの現地時間に変換されます。

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

[...]

マニュアルのこの部分では、TimeZone構成パラメーターで許可される内容を扱います(したがって、 AT TIME ZONE構文)。

manual you quote の質問のさらに下の部分はTime Zone Inputtimestampリテラルで、前述のISO-8601規則に従います。

thisマニュアルの一部SET TIME ZONEに許可されている内容を説明する必要があります(したがって、AT TIME ZONE構成):

TIME ZONE

SET TIME ZONE値はSET timezone TOvalueのエイリアスです。構文SET TIME ZONEでは、タイムゾーンを指定するための特別な構文を使用できます。有効な値の例を次に示します。

'PST8PDT'
カリフォルニア州バークレーのタイムゾーン。

'Europe/Rome'
イタリアのタイムゾーン。

-7
UTCから7時間西のタイムゾーン(PDTに相当)。正の値はUTCの東側です。

INTERVAL '-08:00' HOUR TO MINUTE
UTCから8時間西のタイムゾーン(PSTに相当)。

[...]

あなたの例ではSET TIME ZONE '+02:00';は間隔のように見えますが、それは間違っています。 INTERVALを明示的に宣言するだけで、Postgresはそれをintervalとして扱います。 '+02:00'は、STDoffsetのもう1つのケースであり、先頭にSTDがないため、デフォルトでUTCになります。そう:

SET TIME ZONE '+02:00';

...は次と同等です。

SET TIME ZONE 'UTC+02:00';

これらの引用 最初のマニュアルページから は道具に思える:

デフォルトのタイムゾーンは、UTCからの一定の数値オフセットとして指定されます。

そして:

ゾーンの省略形の妥当性のチェックがないため、POSIXスタイルのタイムゾーン機能が誤って偽の入力を受け入れる可能性があることに注意する必要があります。たとえば、SET TIMEZONE TO FOOBAR0は機能し、システムはUTCのかなり独特な省略形を効果的に使用します。留意すべきもう1つの問題は、POSIXタイムゾーン名では、グリニッジの西側の場所に正のオフセットが使用されることです。それ以外の場所では、PostgreSQLは正のタイムゾーンオフセットがグリニッジの東にあるというISO-8601規則に従います。

しかし、マニュアルには、STDの部分が仕様からmissingである可能性があるとは記載されていないようです。ドキュメントのバグのようです...

2