2013-10-30 105 views
9

我在多個不同時區(以及時間段)使用不同的數據庫,以及通常會產生問題的一件事是日期/時間定義。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 BC,但是有沒有像在SQL Server中那樣以編程方式獲取此值的方法(例如作爲格式化的日期字符串)?

+1

你可以在SQL Server中稱這個「0 date」爲基準日期,但如果你認爲它也是支持的最小日期(並且從你的措辭看起來確實如此),那麼你錯了。它將轉換爲'1900-01-01','smalldatetime'是唯一的日期/時間類型,它不能處理早於此日期的日期。可以說是更廣泛使用的'datetime'支持的日期可以低至'1753-01-01',而更新的類型'date','datetime2','datetimeoffset'支持低至'0001-01-01'的值,僅爲FYI。 –

+0

由於我正在尋找一個參考,而不是最小值(儘管我儘管最小值可以作爲參考...),我會堅持這一點:select to_timestamp(0):: date; – doublebyte

回答

4

最早的時間戳是'-infinity'。這是一個特殊的價值。另一面是「無限」,比任何特定的時間戳晚。

我不知道如何獲得這個編程式的方法。我只是使用硬編碼的值,你可能會使用NULL。這意味着你必須在客戶端處理無限。

+0

謝謝。爲了補充說明,下面是legel查詢:'select('-infinity':: timestamptz)>('2000-01-01':: timestamptz)'和'select('infinity':: timestamptz)>( '2000-01-01':: timestamptz)'在x86_64-pc-linux-gnu上的'PostgreSQL 9.6.2上分別生成'true'和'false',由gcc編譯(Ubuntu 4.8.2-19ubuntu1)4.8.2 ,64位「。 –

8

The manual states the values爲:

  • Low值:BC 4713
  • 高值:AD 294276

與警告,克里斯注意,-infinity也支持。

查看注意事項以後在手冊的同一頁;只有在使用整數時間戳時,上述情況纔是真實的,這是PostgreSQL所有最近版本中默認的。如有疑問:

SHOW integer_datetimes; 

會告訴你。如果您使用的是浮點日期時間,則可以獲得更大的範圍和更少(非線性)的精度。任何以編程方式制定最低限度的企圖都必須應對這一限制。

PostgreSQL不僅允許您將零投到時間戳以獲得最小可能的時間戳,如果您使用浮點日期時間,這也不會有多大意義。您可以使用 Julian日期轉換功能,但是這給你時代不是最小時間

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需要雙倍的時間,儘管這些天時間戳存儲爲整數?)。

我認爲只要讓時間戳範圍成爲任何時間戳就不會出現錯誤,這可能是最明智的做法。畢竟,有效的時間戳的範圍是不連續的:

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'; 

所以你不能假設,僅僅因爲一個值是兩個有效的時間戳之間,這是它自有效。

+0

事實上,PostgreSQL接受的值延長了允許的時間間隔,而不是拋出錯誤,這真的很奇怪。我認爲計算最小日期是有意義的,因爲從支持的最小整數計算日期(或Craig的答案提示BigInt)。在PostgreSQL 9.3手冊中,聲明最小支持的BigInt是-9223372036854775808。因此,我應該能夠計算出這樣的最短日期:「select to_timestamp(-9223372036854775808):: date」,結果爲「294247-01-10」,與手冊中建議的4713 BC不匹配! ! – doublebyte

+0

@doublebyte通過'select extract(從TIMESTAMP'紀元'294247-01-10'紀元')的輸出產生了更加奇怪的結果。日期函數在極端值下的正確性並不令人信服。 –