3

タイムゾーンなしのタイムスタンプを持つテーブルがあります。YYYY-MM-DD HH:MM:SS

太平洋の「P」または山の「M」のいずれかであるフィールド「タイムゾーン」。

「タイムスタンプ付きタイムスタンプ」タイプのフィールドを作成する必要があります

私が持っている 2 つのフィールドを考えると、夏時間を正しく考慮してこれを行う方法はありますか?

具体的には: タイムスタンプ: 2013-11-03 01:00:00 タイムゾーン: "P" は次のようになります: 2013-11-03 01:00:00-07

およびタイムスタンプ: 2013-11-03 03:00:00 タイムゾーン: "P" は次のようになります: 2013-11-03 03:00:00-08

4

3 に答える 3

1

TIMESTAMP WITHOUT TIME ZONETIMESTAMP WITH TIME ZONE( )の違いはTIMESTAMPTZ、名前を考えると非常に理解しにくい場合があります。(実際、仕様はかなり混乱しているように見えるため、さまざまな RDBMS が異なる方法で実装しています。)

PostgreSQL では、どちらのタイプも値が格納されたときに値のタイム ゾーンを格納しませんがTIMESTAMPTZ、UTC 参照に基づく正確な瞬間として値を格納しますが、TIMESTAMP WITHOUT TIME ZONE常に相対的です。

  • クエリが実行TIMESTAMPTZされると、クライアントによって構成された現在のタイム ゾーンでの時点と同じ時点 (世界のどの地域であれ) が最初に保存された時点と同じ時点を表すように が調整されます。
  • ATIMESTAMP WITHOUT TIME ZONEは、クエリ元のタイム ゾーンが異なっていても、クライアントによって構成されたタイム ゾーンに対して常に同じ値になり2013-11-03 03:00:00ます。

おそらく、入力値のあいまいさを補うために、「タイムゾーン」列 (PまたはM) を使用したと思われます。TIMESTAMP WITHOUT TIME ZONE

原則として、タイムスタンプを保存したタイムゾーンと同じ相対タイム ゾーンにいる場合は、同じ値が返されるはずですUS/Pacific。ゾーン、あなたは戻るべきです。ただし、これは相対値に曖昧性がない場合にのみ有効です。2013-11-03 03:00:00P2013-11-03 03:00:00

ここでの最初の例の問題は、すでにいくつかのあいまいさがあることです:

タイムスタンプ: 2013-11-03 01:00:00 タイムゾーン: "P" は次のようになります: 2013-11-03 01:00:00-07

2013-11-03 01:00:00US/Pacificは、タイム ゾーン内の 2 つの異なる瞬間を表すことができるため、 と だけ2013-11-03 01:00:00"P"は、回復できない情報を既に失っています。

その時点での DST 設定に応じて「-08」と「-07」の間で変更したいだけの場合、これは自動的に行われますがTIMESTAMPTZ、最初にa を使用する必要がありました。あなたが表現していた時間の正確な瞬間。

次の例では、最初のタイム ゾーンが保持されているため、'-08' と '-07' の間の変更を確認できます。

SET time zone 'US/Pacific';

SELECT t AS "Date/Time for US/Pacific",
       t AT time zone 'UTC' "Date/Time in UTC"
FROM (VALUES
    ('2013-11-03 00:00:00-07'::timestamptz),
    ('2013-11-03 01:00:00-07'::timestamptz),
    ('2013-11-03 02:00:00-07'::timestamptz),
    ('2013-11-03 03:00:00-07'::timestamptz)) AS v(t);

結果:

| DATE/TIME FOR US/PACIFIC | DATE/TIME IN UTC    |
|--------------------------|---------------------|
| 2013-11-03 00:00:00-07   | 2013-11-03 07:00:00 |
| 2013-11-03 01:00:00-07   | 2013-11-03 08:00:00 |
| 2013-11-03 01:00:00-08   | 2013-11-03 09:00:00 |
| 2013-11-03 02:00:00-08   | 2013-11-03 10:00:00 |

残念ながら、2 つのフィールドだけで DST の変更を処理する方法はありません。

これらの問題をよりよく理解するために、PostgreSQL マニュアルの日付/時刻型のセクションを読むだけでなく、AT TIME ZONEドキュメントの表の「戻り値の型」列に注意を払うことは確かに価値があります。

于 2013-09-28T14:31:09.060 に答える
1

まず、結果が例えば になると言った場合2013-11-03 01:00:00-07、これは実際には SQL クライアントのタイムゾーン設定に依存することを付け加えておく必要があります。たとえば、ヨーロッパ時間のセッションが2013-11-03 01:00:00-07a の値として読み取られることはありtimestamp with time zoneません。これは、ヨーロッパの国がGMT-07.

つまり、AT TIME ZONEコンストラクトを a に適用して変換を行うことができますtimestamp without time zone

US/Pacificこれをタイムゾーンから実行すると仮定します。

SET time zone 'US/Pacific';

SELECT t AT TIME ZONE 
     case z when 'P' then 'US/Pacific' when 'M' then 'US/Mountain' end  
  from (values
    ('2013-11-03 01:00:00'::timestamp, 'P'),
    ('2013-11-03 03:00:00'::timestamp, 'P')
  ) as v(t,z);

結果は次のとおりです。

        タイムゾーン        
------------------------
 2013-11-03 01:00:00-08
 2013-11-03 03:00:00-08

2013-11-03 01:00:00 AT time zone 'US/Pacific'タイムゾーンで最初に発生し、次にDST 切り替え後のタイムゾーン-07で 2 回目の時間スパンに属しているため、あいまいさがあります。-08postgres の解釈は、-08タイムゾーンで見ることです。前の分を考慮すると、-07タイムゾーンに分類されます。

于 2013-09-28T11:24:42.793 に答える
0

これがあなたにとって意味があるかどうかを確認してください

set timezone to 'PST8PDT';

select now();
              now              
-------------------------------
 2013-09-28 03:24:20.169189-07

select ts,
    ts at time zone 'PST' as "PST",
    ts at time zone 'PDT' as "PDT"
from (values
    ('2013-11-03 01:00:00'::timestamp),
    ('2013-11-03 02:00:00'),
    ('2013-11-03 03:00:00')
) s (ts)
;
         ts          |          PST           |          PDT           
---------------------+------------------------+------------------------
 2013-11-03 01:00:00 | 2013-11-03 01:00:00-08 | 2013-11-03 01:00:00-07
 2013-11-03 02:00:00 | 2013-11-03 02:00:00-08 | 2013-11-03 01:00:00-08
 2013-11-03 03:00:00 | 2013-11-03 03:00:00-08 | 2013-11-03 02:00:00-08
于 2013-09-28T11:11:46.973 に答える