私はこれに答えていました 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の結果が同じであることを確認しただけです。
documentation によると、名前や略語を使用してもかまいません。
これはバグですか?
何か間違ったことをしていますか?
誰かがこの結果を説明できますか?
[〜#〜] edit [〜#〜]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です。
EDIT22012-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
実際、ドキュメントには、タイムゾーンの名前と省略形の動作が異なることが明確に記載されています。
つまり、これは略語とフルネームの違いです。略語は常にUTCからの固定オフセットを表しますが、フルネームのほとんどはローカルの夏時間規則を意味するため、2つの可能なUTCオフセットがあります。 参考
FWIW、その同じ参照はまた言います
Type time with time zoneを使用することはお勧めしません(レガシーアプリケーションおよびSQL標準への準拠のためにPostgreSQLでサポートされていますが)。
そしてそれはまだそれの要点ではありません!先ほど 非常によく似た問題 に遭遇しました。
タイムゾーンの略語の主な短所はすでにここに示されています。DST(夏時間)は考慮されていません。主な長所:シンプルで優れたパフォーマンス。 DSTルールを考慮すると、タイムゾーン名slowが比較されます。タイムゾーンの省略形は単純なシンボリック時間オフセットであり、タイムゾーン名は常に変化する一連のルールに従います。私は SOに関するこの関連回答 でベンチマークを実行しましたが、違いは顕著です。ただし、セットに適用する場合、通常はタイムゾーン名を使用して、行ごとに異なるDSTステータス(および履歴の違い)をカバーする必要があります。
[〜#〜] cet [〜#〜]について話している。本当にトリッキーな部分は、 "CET"が(明らかに)タイムゾーンの省略形だけではなく、でもあるaタイムゾーン名、少なくとも私のインストールによると(ロケール「de_AT.UTF-8」を使用したDebian Squeeze上のPostgreSQL 9.1.6)そして私がこれまで見てきた他のすべて。 Postgresは、可能な場合は基盤となるOSのロケール情報を使用するため、これらの詳細について説明します。
自分で見て:
SELECT * FROM pg_timezone_names WHERE name = 'CET';
SELECT * FROM pg_timezone_abbrevs WHERE abbrev = 'CET';
Postgresはフルネームよりも略称を選びます。したがって、タイムゾーン名でCETを見つけたとしても、式'2012-01-18 01:00 CET'::timestamptz
は、タイムゾーンの省略形の微妙に異なるルールに従って解釈されます。
それがロードされたフットガンでない場合、私は何をしているのかわかりません。
あいまいさを回避するには、タイムゾーン名 'Europe/Berlin'(または私の場合は 'Europe/Vienna'-これは、歴史的な違いを除いて実質的に同じです)を使用します。 上記で触れた密接に関連した質問 でトピックの詳細を確認してください。
最後に、DSTのモロニックコンセプトについて深く感じた軽蔑を表明します。それは存在から取り除かれ、二度と話されるべきではありません。
これをチェックして:
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です。