1

今後数年間、毎日1時間ごとに発生するイベントを保存するテーブルをPostgresに作成しようとしています。そこで、次の式を使用して列を作成しました。

INSERT INTO tablename(time) 
SELECT CAST('2013-01-01' AS DATE) + (n || ' hour')::INTERVAL 
 FROM generate_series(0, 100000) n;

この列のデータ型として、タイム ゾーン付きのタイムスタンプを選択し、この方法で夏時間が自動的に考慮されることを期待しました。(ちなみに、私のデフォルトのタイムゾーンは CET なので、DST が適用される場合は UTC+1 または UTC+2 です)。上記のクエリの結果として、次のようになります。

  • 2013-03-31 00:00:00 +01
  • 2013-03-31 01:00:00 +01
  • 2013-03-31 03:00:00 +02
  • 2013-03-31 03:00:00 +02
  • 2013-03-31 04:00:00 +02
  • ...
  • 2013-10-27 00:00:00 +02
  • 2013-10-27 01:00:00 +02
  • 2013-10-27 02:00:00 +01
  • 2013-10-27 03:00:00 +01
  • 2013-10-27 04:00:00 +01
  • ...

UTC へのオフセットが変更され、3 月 31 日は 23 時間しかないため 02:00 が除外されると予想しましたが、10 月 27 日には 02:00 しかないのに、なぜ 03:00 が 2 回あるのかわかりません。この日は 25 時間なので、2 回ではなく 1 回です。私が達成したいのは、すべての年で 3 月の特定の日の 2 時がスキップされず (対応する値に「な」または何かを入力したい)、3 時のエントリが 2 つあることです。 10 月の特定の日に (ただし 3 月ではない)、次の形式の列を取得します (1 は 00:00 から 1:00 までの時間を表し、2 は 1:00 から 2:00 を表します)。など):

  • 2013-03-31 1 +01
  • 2013-03-31 2 +01
  • 2013-03-31 3 +02
  • 2013-03-31 4 +02
  • 2013-03-31 5 +02
  • ...
  • 2013-10-27 1 +02
  • 2013-10-27 2 +02
  • 2013-10-27 3A +02
  • 2013-10-27 3B +01
  • 2013-10-27 4 +01
  • 2013-10-27 5 +01
  • ...

誰かがそれをどうやって進めるか考えていますか? 私は基本的に何か間違ったことをしていますか?フォーマットだけの問題ですか?関数を書く必要がありますか?どんな助けでも大歓迎です。ありがとうございました。

4

2 に答える 2

0

タイム ゾーンの設定に関係なく、タイムスタンプは常に UTC として保存されます。説明書より

タイム ゾーン付きタイムスタンプの場合、内部に保存される値は常に UTC (Universal Coordinated Time、グリニッジ標準時 (GMT) として知られています) です。明示的なタイム ゾーンが指定されている入力値は、そのタイム ゾーンの適切なオフセットを使用して UTC に変換されます。入力文字列にタイム ゾーンが指定されていない場合は、システムの TimeZone パラメータで指定されたタイム ゾーンにあると見なされ、タイム ゾーンのオフセットを使用して UTC に変換されます。

set time zone 'CET';

drop table if exists events;
create table events (
    tstz timestamp with time zone
);
insert into events (tstz)
select generate_series('2013-01-01', '2013-10-28', interval '1 hour') s(tstz)
;

関数の使用に注意してくださいgenerate_series

select
    tstz at time zone 'UTC' as "UTC",
    tstz at time zone 'CET' as "CET",
    tstz at time zone 'CEST' as "CEST",
    tstz as "LOCAL"
from events
where date_trunc('day', tstz) in ('2013-03-31', '2013-10-27')
order by tstz
;
         UTC         |         CET         |        CEST         |         LOCAL          
---------------------+---------------------+---------------------+------------------------
 2013-03-30 23:00:00 | 2013-03-31 00:00:00 | 2013-03-31 01:00:00 | 2013-03-31 00:00:00+01
 2013-03-31 00:00:00 | 2013-03-31 01:00:00 | 2013-03-31 02:00:00 | 2013-03-31 01:00:00+01
 2013-03-31 01:00:00 | 2013-03-31 02:00:00 | 2013-03-31 03:00:00 | 2013-03-31 03:00:00+02
 2013-03-31 02:00:00 | 2013-03-31 03:00:00 | 2013-03-31 04:00:00 | 2013-03-31 04:00:00+02
 2013-03-31 03:00:00 | 2013-03-31 04:00:00 | 2013-03-31 05:00:00 | 2013-03-31 05:00:00+02
...
 2013-10-26 22:00:00 | 2013-10-26 23:00:00 | 2013-10-27 00:00:00 | 2013-10-27 00:00:00+02
 2013-10-26 23:00:00 | 2013-10-27 00:00:00 | 2013-10-27 01:00:00 | 2013-10-27 01:00:00+02
 2013-10-27 00:00:00 | 2013-10-27 01:00:00 | 2013-10-27 02:00:00 | 2013-10-27 02:00:00+02
 2013-10-27 01:00:00 | 2013-10-27 02:00:00 | 2013-10-27 03:00:00 | 2013-10-27 02:00:00+01
 2013-10-27 02:00:00 | 2013-10-27 03:00:00 | 2013-10-27 04:00:00 | 2013-10-27 03:00:00+01
 2013-10-27 03:00:00 | 2013-10-27 04:00:00 | 2013-10-27 05:00:00 | 2013-10-27 04:00:00+01
 2013-10-27 04:00:00 | 2013-10-27 05:00:00 | 2013-10-27 06:00:00 | 2013-10-27 05:00:00+01

列が上記の列のように使用されtimestamp with timestampずに selectec である場合、そのタイムスタンプのサーバー タイム ゾーンで出力されます。そのため、時間の欠落や重複が発生します。at time zoneLOCAL

あなたの望む出力は間違っていると思います。しかし、いくつかのクエリfuで達成可能です

実際の出力を再現できません。サーバーのタイムゾーンは?

show time zone;
 TimeZone 
----------
 CET
于 2014-03-16T19:19:26.750 に答える