web-dev-qa-db-ja.com

PostgreSQLでサポートされている最も古いタイムスタンプ

私はさまざまなタイムゾーン(および期間)でさまざまなデータベースを使用していますが、通常問題が発生するのは、日付/時刻の定義です。

このため、日付は開始値への参照であるため、計算方法を追跡するために、基準日を保存しようとしています。つまり、その特定のコンピューター/データベースでサポートされている最小の日付。

私がよく見ている場合、これはRDBMSとそのタイプの特定のストレージに依存します。 SQL Serverで、この「基準日」を計算するいくつかの方法を見つけました。

SELECT CONVERT(DATETIME, 0) 

または

SELECT DATEADD(MONTH, 0, 0 ) 

またはこのようなキャストでさえ:

DECLARE @300 BINARY(8) 
SET @300 = 0x00000000 + CAST(300 AS BINARY(4))
set @dt=(SELECT CAST(@300 AS DATETIME) AS BASEDATE)
print CAST(@dt AS NVARCHAR(100))

(@dtは日時変数です)

私の質問は、PostgreSQLで基準日を計算する同様の方法がありますか?つまり、サポートされている最小の日付であり、すべての計算に基づいている値ですか?

date type の説明から、サポートされる最小の日付は紀元前4713年であることがわかりますが、プログラムでこの値を取得する方法はあります(たとえば、フォーマットされた日付文字列として) )、SQL Serverの場合と同じように?

13
doublebyte

マニュアルには値が記載されています 次のようになります。

  • 低い値:紀元前4713年
  • 高い値:294276 AD

クリスが指摘したように、警告がありますが、-infinityもサポートされています。

マニュアルの同じページの後半にあるnoteを参照してください。上記は、整数タイムスタンプを使用している場合にのみ当てはまります。これは、漠然と最近のすべてのバージョンのPostgreSQLのデフォルトです。疑わしい場合:

SHOW integer_datetimes;

教えてくれます。代わりに浮動小数点日時を使用している場合は、範囲が広くなり、精度が低くなります(非線形)。プログラムで最小値を計算しようとすると、その制限に対処する必要があります。

PostgreSQLでは、タイムスタンプにゼロをキャストして可能な最小のタイムスタンプを取得するだけでなく、浮動小数点の日時を使用している場合、これはあまり意味がありません。 canユリウス日変換関数を使用しますが、これによりEpochではなくminimum time

postgres=> select to_timestamp(0);
      to_timestamp      
------------------------
 1970-01-01 08:00:00+08
(1 row)

負の値を受け入れるためです。負のmaxintを与えることはうまくいくと思うかもしれませんが、結果は驚くべきものであり、ここにラップアラウンドバグが潜んでいるのではないかと思います。

postgres=> select to_timestamp(-922337203685477);
          to_timestamp           
---------------------------------
 294247-01-10 12:00:54.775808+08
(1 row)

postgres=> select to_timestamp(-92233720368547);
          to_timestamp           
---------------------------------
 294247-01-10 12:00:54.775808+08
(1 row)

postgres=> select to_timestamp(-9223372036854);
         to_timestamp         
------------------------------
 294247-01-10 12:00:55.552+08
(1 row)

postgres=> select to_timestamp(-922337203685);
ERROR:  timestamp out of range
postgres=> select to_timestamp(-92233720368);
          to_timestamp           
---------------------------------
 0954-03-26 09:50:36+07:43:24 BC
(1 row)

postgres=> select to_timestamp(-9223372036);
         to_timestamp         
------------------------------
 1677-09-21 07:56:08+07:43:24
(1 row)

(おそらく、最近のタイムスタンプは整数として格納されていますが、to_timestampが2倍になるという事実に関連していますか?).

タイムスタンプの範囲を、エラーが発生しない任意のタイムスタンプにするのがおそらく最も賢明だと思います。結局のところ、有効なタイムスタンプの範囲は連続的ではありません。

postgres=> SELECT TIMESTAMP '2000-02-29';
      timestamp      
---------------------
 2000-02-29 00:00:00
(1 row)

postgres=> SELECT TIMESTAMP '2001-02-29';
ERROR:  date/time field value out of range: "2001-02-29"
LINE 1: SELECT TIMESTAMP '2001-02-29';

したがって、値が2つの有効なタイムスタンプの間にあるという理由だけで、それが自己有効であると想定することはできません。

10
Craig Ringer

最も早いタイムスタンプは「-無限大」です。これは特別な値です。反対側は、特定のタイムスタンプよりも遅い「無限大」です。

これをプログラムで取得する方法がわかりません。 NULLを使用するのと同じように、ハードコードされた値を使用します。つまり、クライアント側で無限大を処理する必要があります。

9
Chris Travers