2012-02-04 3 views
4

「日付+時刻」をPostgreSQLデータベースに保存する方法を教えてください。タイムゾーンとは無関係に同じ日付と時刻を取得する方法

この私が達成したいものです:世界のどこかで

  1. は、どのように私は(例えば)に発生したすべてのエントリを持つことができます2012年1月1日に午後12時〇〇分00秒ローカルタイム?
  2. すべてのエントリをUTC時刻に従って日付順に並べ替えて表示します。 (2012年のニューヨークの新年はロンドンの新年よりも新しい)

データはどのように保存すればよいですか? PostgreSQLのすべての時間をUTCで内部的に(PostgreSQL documentation)読み込んだので、ユーザのタイムゾーンは実際には失われています。

私は、「タイムゾーンなしのタイムスタンプ」をタイプして1列を使用すべきだと思う:

  • ポイント1は、簡単です。
  • とタイプ「文字列」の別の列を持つ
  • 私はタイムゾーンの文字列を格納します(例:アメリカ/ニューヨーク) が、その後、ポイント2は、まだやるのは難しいようです....

私は私が願っています明らかです。

編集新しいアイデア:私は2つのタイムスタンプを保存すると思う:タイムゾーン(1 OK)のないものとタイムゾーンを持つ1(2 OK)

答えて

1

はい、PostgreSQLはすべてのタイムスタンプを内部的にUTCとして保存します。 timestamp with time zoneの場合、タイムゾーンオフセットはUTCの時刻を調整するためにのみ適用されますが、明示的には格納されません。

私はタイムゾーン文字列を保存しないでください(正確ではない)。これは、夏時間やその他の国際時間枠の奇妙な部分を考慮する必要があるため、後で高価な計算を必要とする可能性があります。

あなたが間隔としてタイムゾーンオフセットを格納することができるいずれかの私はこのrelated answerで実証ように(整数として4バイトを要する)または秒の数値量(12バイトをとります)。

または、すでに提案したように:UTCタイムスタンプに加えてローカルタイムスタンプを保存してください(8バイト)。それはあなたの仕事を簡単にするでしょう。次のデモを考えてみましょう::

-- DROP TABLE tbl; 
CREATE TEMP TABLE tbl (id int, ts_tz timestamp with time zone, ts timestamp); 
INSERT INTO tbl VALUES 
(1,'2012-1-1 00:00+01','2012-1-1 00:00+01') 
,(2,'2012-1-1 00:00+02','2012-1-1 00:00+02') 
,(3,'2012-1-1 00:01+03','2012-1-1 00:01+03') 
,(4,'2012-1-1 00:02+04','2012-1-1 00:02+04'); 

質問1のためのクエリ:質問2について

SELECT * 
FROM tbl 
WHERE ts = '2012-1-1 00:00'::timestamp; 

id |   ts_tz   |   ts 
----+------------------------+--------------------- 
    1 | 2012-01-01 00:00:00+01 | 2012-01-01 00:00:00 
    2 | 2011-12-31 23:00:00+01 | 2012-01-01 00:00:00 

問合せ:

SELECT * 
FROM tbl 
ORDER BY ts_tz; 

id |   ts_tz   |   ts 
----+------------------------+--------------------- 
    4 | 2011-12-31 21:02:00+01 | 2012-01-01 00:02:00 
    3 | 2011-12-31 22:01:00+01 | 2012-01-01 00:01:00 
    2 | 2011-12-31 23:00:00+01 | 2012-01-01 00:00:00 
    1 | 2012-01-01 00:00:00+01 | 2012-01-01 00:00:00 

トリッキーな部分このソリューションでは、入力することであってもよいですローカルタイムスタンプ。すべてのデータがローカルに入力されている限り、簡単です。しかし、たとえばロサンゼルスにニューヨークのデータを入力する場合は、考慮する必要があります。そのためAT TIME ZONE constructを使用してください:私は、入力としてタイムゾーンとタイムスタンプを使用する方法

SELECT ('2012-1-1 00:00+00' AT TIME ZONE 'America/New_York')::timestamp 
    , ('2012-1-1 00:00+00' AT TIME ZONE 'America/Los_Angeles')::timestamp 

     timezone  |  timezone 
---------------------+--------------------- 
2011-12-31 19:00:00 | 2011-12-31 16:00:00 

注意を。 AT TIME ZONEは、タイムゾーンの有無にかかわらずタイムスタンプの結果が異なります。

0

私はあなたが文字列として日付を格納し、ISO 8601を使用することができると思いますまたはRFC 2822を参照して、タイムゾーンも保存してください。 また、比較オプションとしてタイムスタンプとタイムゾーンを2つの異なる列に格納することもできます。

+0

文字列として日付/時刻を格納するのは非常に汚い方法であり、避けてください。 – Skuld

+0

データベースの日付/時刻フィールドは常に文字列ではありませんか? そして、私はあなたの質問で比較することに同意しますが、ISO 8601の文字列として格納する必要がない場合は、問題ありません。 –

+0

postgresqlが他のデータベースエンジンと非常に異なる何かをしない限り、datetimeは決して文字列として格納されません過去の特定の日付/時刻から定義された時間量を表す整数値) – Skuld