2013-10-30 45 views
9

tarafından desteklenen en eski Zaman Damgası, farklı saat dilimlerinde (ve zaman aralıklarında) farklı veritabanlarıyla çalışıyorum ve normalde sorunları oluşturan bir şey, tarih/saat tanımıdır.PostgreSQL

Bu nedenle, ve bir tarihin başlangıç ​​değerine referans olması nedeniyle, nasıl hesaplandığını takip etmek için temel tarihi depolamaya çalışıyorum; yani, söz konusu bilgisayar/veritabanında desteklenen minimum tarih;

Eğer iyi görüyorsam, bu RDBMS'ye ve türün belirli depolamasına bağlıdır. SQL Server'da, bu "temel tarihi" hesaplamanın birkaç yolunu buldum;

SELECT CONVERT(DATETIME, 0) 

veya

SELECT DATEADD(MONTH, 0, 0) 

veya böyle hatta bir döküm

:

Benim sorum (@dt bir datetime değişken olduğu), benzer bir

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)) 

yoktur

PostgreSQL'te temel tarihin hesaplanma şekli, yani: minimum hesaplanan değer ve tüm hesaplamalar bazında olan değer nedir? date type açıklamasından

, ben desteklenen minimum tarih 4713 M.Ö., ama SQL Server olduğu gibi orada, (biçimlendirilmiş bir tarih dizesi olarak örneğin) programlı bu değeri almanın bir yolu olduğunu görebilir?

+1

SQL Server'da bu "0 date" temel tarihini çağırabilirsiniz, ancak aynı zamanda desteklenen minimum tarih olduğunu düşünüyorsanız (ve ifadenizden yaptığınız gibi görünür), yanılıyorsunuz demektir. '1900-01-01' ye dönüşür ve 'smalldatetime', daha önceki tarihlerle başa çıkamayan tek tarih/saat türüdür. Muhtemelen daha yaygın olarak kullanılan 'datetime', tarihleri ​​"1753-01-01" ve yeni türleri "date", "datetime2", "datetimeoffset" değerlerini "0001-01-01", sadece FYI'ye kadar destekler. –

+0

En düşük değerden ziyade bir referans aradığım için (minimum değer referans olarak verilse de ...), buna bağlı kalacağım: select to_timestamp (0) :: date; – doublebyte

cevap

4

En eski zaman damgası '-infinity'dir. Bu özel bir değer. Diğer taraf, herhangi bir belirli zaman damgasından daha sonra gelen 'sonsuzluk'tur.

Bu şekilde programlamanın bir yolunu bilmiyorum. Sadece NULL kullanabileceğiniz şekilde kodlanmış değeri kullanırdım. Bu, müşteri tarafında sonsuzlukları ele almanız gerektiği anlamına gelir.

+0

Teşekkürler. Ve buna ek olarak, aşağıdakiler legel sorgularıdır: 'select ('-infinity' :: timestamptz)> ('2000-01-01' :: timestamptz)' ve 'select ('infinity' :: timestamptz)> ('2000-01-01' :: timestamptz) 'gcc (Ubuntu 4.8.2-19ubuntu1) tarafından derlenen x86_64-pc-linux-gnu üzerindeki PostgreSQL 9.6.2 üzerinde 'true' ve' false' üretme 64-bit. –

8

The manual states the values olarak:

  • Düşük değer: 4713 M.Ö.
  • Yüksek değeri: -infinity da desteklendiğini 294276 AD ikaz ile

Chris belirtildiği gibi.

El kitabında aynı sayfada bulunan not'a bakın; Yukarıdakiler, PostgreSQL'in tüm son sürümlerinde varsayılan olan tamsayı zaman damgalarını kullanıyorsanız doğrudur. Şüpheniz varsa:

size söyleyecektir. Bunun yerine kayan nokta verileri kullanıyorsanız, daha fazla aralık ve daha az (doğrusal olmayan) hassasiyet elde edersiniz. Minimum programatik olarak çalışma girişimi, bu kısıtlamayla baş etmelidir.

PostgreSQL, mümkün olan en düşük zaman damgasını elde etmek için bir zaman damgasını sıfıra indirmenize izin vermez, aynı zamanda kayan nokta süreleri kullanıyorsanız bu çok anlamlı olur.Sen Julian tarih dönüşüm fonksiyonunu kullanabilirsiniz, ancak bu size çağı değil minimum zaman verir:

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

negatif değerleri kabul çünkü. Sen bunu olumsuz maxlnt vererek işe diye düşünüyor, ancak sonuçlar burada gizlenen bir etrafı sarılan hata var acaba nereye noktasına şaşırtıcı şunlardır:

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) 

(Belki ilgili gerçeği buna to_timestamp bu günlerde tamsayılar olarak zaman damgaları depolanmış olsa bile, bir çift alır?).

Sanırım, zaman damgasının aralığındaki herhangi bir zaman damgasının hata yapmasına izin vermemesi muhtemelen en akıllıca olacaktır. Sonuçta, Geçerli zaman damgası aralığı sürekli değildir:

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

böylece bir değer iki geçerli zaman damgaları arasındaki sırf kabul edemeyiz, kendi kendini geçerlidir.

+0

Aslında PostgreSQL, hata atmak yerine izin verilen aralığı uzatan değerleri kabul etmesi gerçekten garip. Minimum destekli tam sayıdan (ya da Craig'in cevabını önerdiği gibi, BigInt) hesaplanan tarih olarak, asgari tarihi hesaplamanın mantıklı olacağını düşünüyorum. PostgreSQL 9.3 kılavuzunda, desteklenen minimum BigInt'in -9223372036854775808 olduğu belirtilmiştir. Bu nedenle, şu gibi asgari tarihi hesaplayabilmeliydim: "select to_timestamp (-9223372036854775808) :: date", sonuçta "294247-01-10" sonucunu verir, kılavuzdaki MÖ 4713 ile eşleşmez! ! – doublebyte

+0

@doublebyte Çıktının çıktısı ile bile garip hale getirildi (TIMESTAMP '294247-01-10' den itibaren); Tarih fonksiyonlarının doğruluğu ile aşırı değerlerde ikna olmadı. –