Geçerli unix zaman damgasını PostgreSQL'den nasıl edinebilirim?


91

Unix zaman damgası , UTC 1 Ocak 1970 gece yarısından bu yana geçen saniye sayısıdır.

PostgreSQL'den doğru unix zaman damgasını nasıl bulurum?

Currenttimestamp.com ve timestamp.1e5b.de ile karşılaştırırken PostgreSQL'den beklenen süreyi alamıyorum:

Bu doğru zaman damgasını döndürür:

SELECT extract(epoch from now());

Bu olmasa da:

SELECT extract(epoch from now() at time zone 'utc');

UTC +02 saat diliminde yaşıyorum. PostgreSQL'den mevcut unix zaman damgasını almanın doğru yolu nedir?

Bu, doğru zaman ve zaman dilimini döndürür:

SELECT now();
              now
-------------------------------
 2011-05-18 10:34:10.820464+02

Başka bir karşılaştırma:

select now(), 
extract(epoch from now()), 
extract(epoch from now() at time zone 'utc');
              now              |    date_part     |    date_part
-------------------------------+------------------+------------------
 2011-05-18 10:38:16.439332+02 | 1305707896.43933 | 1305700696.43933
(1 row)

Unix timestamp from the web sites:
1305707967

Yanıtlar:


82

Postgreslerde, ve olarak timestamp with time zonekısaltılabilir . Basitlik için kısa tip isimleri kullanacağımtimestamptztimestamp without time zonetimestamp

Unix zaman damgasını bir postgres'den almak , dediğiniz timestamptzgibi now(), basittir:

select extract(epoch from now());

Gerçekten timestamptzde dahil olmak üzere herhangi bir türden mutlak zaman alma hakkında bilmeniz gereken her şey now().

Sadece timestamptarla varken işler karmaşıklaşıyor .

Bu alana timestamptzbenzer verileri koyduğunuzda now(), önce belirli bir saat dilimine dönüştürülecek (açık bir şekilde at time zoneveya oturum saat dilimine dönüştürülerek) ve saat dilimi bilgileri atılacaktır . Artık mutlak bir zaman değil. Bu nedenle genellikle zaman damgalarını timestampnormalde kullanacağınız gibi saklamak istemezsiniz timestamptz- belki de her saat 6: 00'da belirli bir tarihte bir film yayınlanır , işte böyle bir kullanım durumudur.

Sadece tek bir saat diliminde çalışırsanız, (mis) ile kurtulabilirsiniz timestamp. Geri dönüş timestamptz, DST ile başa çıkmak için yeterince zekidir ve zaman damgalarının, dönüşüm amaçları için geçerli zaman diliminde olduğu varsayılır. İşte GMT / BST için bir örnek:

select '2011-03-27 00:59:00.0+00'::timestamptz::timestamp::timestamptz
     , '2011-03-27 01:00:00.0+00'::timestamptz::timestamp::timestamptz;

/*
|timestamptz           |timestamptz           |
|:---------------------|:---------------------|
|2011-03-27 00:59:00+00|2011-03-27 02:00:00+01|
*/

DBFiddle

Ancak, aşağıdaki kafa karıştırıcı davranışa dikkat edin:

set timezone to 0;

values(1, '1970-01-01 00:00:00+00'::timestamp::timestamptz)
    , (2, '1970-01-01 00:00:00+02'::timestamp::timestamptz);

/*
|column1|column2               |
|------:|:---------------------|
|      1|1970-01-01 00:00:00+00|
|      2|1970-01-01 00:00:00+00|
*/

DBFiddle

Bunun nedeni :

PostgreSQL, türünü belirlemeden önce değişmez bir dizgenin içeriğini asla incelemez ve bu nedenle her ikisine de […] zaman dilimi olmadan zaman damgası olarak davranır. Bir değişmezin zaman dilimi ile zaman damgası olarak değerlendirildiğinden emin olmak için doğru açık türü belirtin… Zaman dilimi olmadan zaman damgası olduğu belirlenen bir değişmezde, PostgreSQL herhangi bir zaman dilimi göstergesini sessizce yoksayır


Sonuçta elde edilen ondalık sayıyı ondalık nokta olmadan bir tam sayıya dönüştürmek için herhangi bir fikir (sayıyı ve ondalık sayıyı büyük bir tam sayı olarak birleştirmek anlamına gelir). Teşekkürler.
WM

Gibi bu ama gerçekten bunu yapmak istemiyorum eminim. Belki de 10'luk bir güçle çarpıp kalan ondalık sayıları atmak istersiniz?
Jack Douglas

2
@WM Belki de böyle? SELECT FLOOR(EXTRACT(epoch FROM NOW())*1000);
Joe23,

21
SELECT extract(epoch from now() at time zone 'utc');

doğru zaman damgası döndürmüyor çünkü postgres saat dilimi dönüştürme işlemi saat dilimi bilgilerini sonuçtan uzaklaştırıyor:

9.9.3. ZAMAN BÖLGEDE

Sözdizimi: zaman dilimi olmayan zaman damgası AT ZAMAN BÖLGESİ zonu
İadeler: zaman
dilimli zaman damgası

Sözdizimi: zaman dilimine sahip zaman damgası AT ZAMAN BÖLGESİ zonu
İadeler: zaman dilimine sahip olmayan
zaman damgası

daha sonra, çıkartma zaman dilimine sahip olmayan zaman damgasına bakar ve yerel bir zaman olarak görür (gerçekte utc olmasına rağmen).

Doğru yol şöyle olurdu:

select now(),
       extract(epoch from now()),                                          -- correct
       extract(epoch from now() at time zone 'utc'),                       -- incorrect
       extract(epoch from now() at time zone 'utc' at time zone 'utc');    -- correct

          now                  |    date_part     |    date_part     |    date_part
-------------------------------+------------------+------------------+------------------
 2014-10-14 10:19:23.726908+02 | 1413274763.72691 | 1413267563.72691 | 1413274763.72691
(1 row)

Son satırda ilk at time zonedönüşüm gerçekleştirilir, ikincisi sonuç için yeni bir saat dilimi atar.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.