ゾーン名がPostgreSQLのバグの「AT TIME ZONE」


12

私はこのstackoverflowの質問に答えていて、奇妙な結果を見つけました:

 select * from  pg_timezone_names where name = 'Europe/Berlin' ;
     name      | abbrev | utc_offset | is_dst 
---------------+--------+------------+--------
 Europe/Berlin | CET    | 01:00:00   | f

そして次のクエリ

select id, 
  timestampwithtimezone, 
  timestampwithtimezone at time zone 'Europe/Berlin' as berlin, 
  timestampwithtimezone at time zone 'CET' as cet 
from data ;
 id  | timestampwithtimezone  |       berlin        |         cet         
 -----+------------------------+---------------------+---------------------
 205 | 2012-10-28 01:30:00+02 | 2012-10-28 01:30:00 | 2012-10-28 00:30:00
 204 | 2012-10-28 02:00:00+02 | 2012-10-28 02:00:00 | 2012-10-28 01:00:00
 203 | 2012-10-28 02:30:00+02 | 2012-10-28 02:30:00 | 2012-10-28 01:30:00
 202 | 2012-10-28 02:59:59+02 | 2012-10-28 02:59:59 | 2012-10-28 01:59:59
 106 | 2012-10-28 02:00:00+01 | 2012-10-28 02:00:00 | 2012-10-28 02:00:00

PostgreSQL 9.1.2とubuntu 12.04を使用しています。
8.2.11で結果が同じであることを確認しました。

ドキュメントによると、名前と略語を使用しても問題ありません。

これはバグですか?
私は何か間違っていますか?
誰かがこの結果を説明できますか?

編集 CETはヨーロッパ/ベルリンではないというコメントに対して。

pg_timezone_namesから値を選択しています。

select * from  pg_timezone_names  where abbrev ='CEST';
 name | abbrev | utc_offset | is_dst 
------+--------+------------+--------

そして

select * from  pg_timezone_names  where abbrev ='CET';
        name         | abbrev | utc_offset | is_dst 
---------------------+--------+------------+--------
 Africa/Tunis        | CET    | 01:00:00   | f
 Africa/Algiers      | CET    | 01:00:00   | f
 Africa/Ceuta        | CET    | 01:00:00   | f
 CET                 | CET    | 01:00:00   | f
 Atlantic/Jan_Mayen  | CET    | 01:00:00   | f
 Arctic/Longyearbyen | CET    | 01:00:00   | f
 Poland              | CET    | 01:00:00   | f
 .....

冬の間、ヨーロッパ/ベルリンは+01です。夏の間は+02です。

EDIT2 2012-10-28では、タイムゾーンは夏時間から冬時間の2:00に変更されました。
この2つのレコードは、ヨーロッパ/ベルリンで同じ値を持ちます。

204 | 2012-10-28 02:00:00+02 | 2012-10-28 02:00:00 | 2012-10-28 01:00:00
106 | 2012-10-28 02:00:00+01 | 2012-10-28 02:00:00 | 2012-10-28 02:00:00

これは、ビッグデータ範囲(夏時間と冬時間)に略語(CETまたはCEST)のいずれかを使用すると、一部のレコードで結果が間違っていることを示しています。「ヨーロッパ/ベルリン」を使用すると良いでしょう。

システム時間を「2012-01-17」に変更し、pg_timezone_namesも変更しました。

select * from  pg_timezone_names  where name ='Europe/Berlin';
     name      | abbrev | utc_offset | is_dst 
---------------+--------+------------+--------
 Europe/Berlin | CEST   | 02:00:00   | t

1
それは2012-10-28 01:30:00CETではなくCESTであると確信しています。
dezso

1
私の知る限りでCETはありません Europe/Berlin -少なくとも夏時間中はそうではありません
a_horse_with_no_name

回答:


9

実際、ドキュメントには、タイムゾーン名と略語の動作が異なることが明確に記載されています。

要するに、これは略語とフルネームの違いです。略語は常にUTCからの固定オフセットを表しますが、フルネームのほとんどはローカル夏時間規則を意味するため、2つの可能なUTCオフセットがあります。参照

FWIW、その同じ参照も言う

タイプゾーンをタイムゾーンと共に使用することはお勧めしません(ただし、PostgreSQLでは、レガシーアプリケーションおよびSQL標準への準拠のためにサポートされています)。


6

そして、それはまだそれの要点ではありません!に遭遇しました少し前に非常によく似た問題

ここでは、タイムゾーンの略語の主な短所が既に説明されています。DST(夏時間)は考慮されていません。主な長所:優れたパフォーマンスをもたらすシンプルさ。DSTルールを考慮すると、タイムゾーン名が比較して遅くなります。タイムゾーンの略語は、単純な記号的なタイムオフセットであり、タイムゾーン名は、常に変化する規則のセットに従います。SOに関するこの関連する回答でベンチマークを実行しましたが、その違いは顕著です。ただし、セットに適用する場合、通常はタイムゾーン名を使用して、行ごとに異なるDSTステータス(および歴史的な違い)をカバーする必要があります。

私たちはCETについて話している。本当に難しいのは、「CET」が(明らかに)タイムゾーンの略語であるだけでなく少なくとも私のインストールでタイムゾーン名でことです(Debian Squeezeでのロケール「de_AT.UTF-8」のPostgreSQL 9.1.6 ")および私がこれまでに見た他のすべて。Postgresが利用可能な場合、基盤となるOSのロケール情報を使用するため、これらの詳細に言及します。

自分で見て:

SELECT * FROM pg_timezone_names WHERE name = 'CET';

SELECT * FROM pg_timezone_abbrevs WHERE abbrev = 'CET';

SQLフィドル。

Postgresはフルネームの略語を選択します。そのため、タイムゾーン名でCETを見つけたとしても、式'2012-01-18 01:00 CET'::timestamptzタイムゾーンの略語の微妙に異なる規則に従って解釈されますます。

それがロードされたフットガンでない場合、私は何がわからない。

あいまいさを避けるため、タイムゾーン名「ヨーロッパ/ベルリン」(または私の場合は「ヨーロッパ/ウィーン」-歴史的な違いを除いて事実上同じです)を使用します。トピックの詳細については、上記の密接に関連した質問の

最後に、DSTのモロニックな概念に対する深く感じられた軽emptを表明したいと思います。それは存在から取り除かれ、二度と話されるべきではありません。


3

これをチェックして:

select  
    '2012-10-28 02:30:00+02'::timestamp with time zone at time zone 'Europe/Berlin' as berlin,
    '2012-10-28 02:30:00+02'::timestamp with time zone at time zone 'CET' as cet,
    '2012-10-28 02:30:00+02'::timestamp with time zone at time zone 'CEST' as cest

+02 CETではなく、ベルリンのCESTです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.