Veri türü timestamp
, kısa adıdır timestamp without time zone
.
Diğer seçenek timestamptz
kısadır timestamp with time zone
.
timestamptz
olan tercih tarih / saat ailede tip anlamıyla. Bu gelmiştir typispreferred
ayarlanan pg_type
ilgili olabilen,:
Dahili depolama ve dönem
Dahili olarak zaman damgaları diskte ve RAM'de 8 bayt depolama alanı kaplar . Postgres dönemindeki mikrosaniye sayısını, 2000-01-01 00:00:00 UTC'yi temsil eden bir tamsayı değeridir.
Postgres ayrıca UNIX döneminden itibaren yaygın olarak kullanılan UNIX zaman sayımı saniye bilgisine sahiptir , 1970-01-01 00:00:00 UTC ve bunu işlevlerde to_timestamp(double precision)
veya kullanır EXTRACT(EPOCH FROM timestamptz)
.
Kaynak kodu:
* Zaman damgalarının yanı sıra aralıkların h / m / s alanları,
* mikrosaniye birimleri ile int64 değerleri. (Bir zamanlar
* saniye birimleriyle çift değerler.)
Ve:
/ * Unix ve Postgres hesaplamasında 0. Günün Julian-tarih eşdeğerleri * /
#define UNIX_EPOCH_JDATE 2440588 / * == tarih2j (1970, 1, 1) * /
#define POSTGRES_EPOCH_JDATE 2451545 / * == tarih2j (2000, 1, 1) * /
Mikrosaniye çözünürlüğü saniyeler için maksimum 6 kesirli basamağa çevirir.
timestamp
Olarak yazılan bir değer Postgres'e hiçbir zaman diliminin açıkça belirtilmediğini bildirir. Geçerli saat dilimi varsayılır. Postgres yanlışlıkla eklenen herhangi bir saat dilimi değiştiricisini yok sayar !timestamp
[without time zone]
Gösterge için saat kaydırılmıyor. Aynı saat dilimi ayarıyla her şey yolunda. Farklı bir saat dilimi ayarı için anlam değişir, ancak değer ve ekran aynı kalır.
timestamptz
Kullanımı timestamp with time zone
oldukça farklıdır. Ben burada kılavuzu alıntı :
Çünkü timestamp with time zone
dahili olarak depolanan değer her zaman UTC'dir (Evrensel Koordineli Zaman ...)
Cesur vurgu benim. Saat dilimi kendisi saklanan asla . Kaydedilen UTC zaman damgasını hesaplamak için kullanılan bir girdi değiştiricidir veya görüntülenen yerel saati hesaplamak için kullanılan çıkış değiştiricisidir. timestamptz
Giriş için bir ofset eklemezseniz , oturumun geçerli saat dilimi ayarı varsayılır. Tüm hesaplamalar UTC zaman damgası değerleri ile yapılır. Birden fazla saat dilimi ile uğraşmanız gerekiyorsa (veya zorunda kalmanız gerekiyorsa) kullanın timestamptz
.
Psql veya pgAdmin gibi istemciler veya libpq aracılığıyla iletişim kuran herhangi bir uygulama (pg gem ile Ruby gibi) geçerli saat dilimi için zaman damgası artı ofseti veya istenen bir saat dilimine göre sunulur (aşağıya bakın). Her zaman aynı noktadır , sadece görüntü formatı değişir. Veya kılavuzun belirttiği gibi :
Tüm saat dilimine uyan tarihler ve saatler dahili olarak UTC'de saklanır.
İstemciye gösterilmeden önce TimeZone yapılandırma parametresi tarafından belirtilen bölgedeki yerel saate dönüştürülür .
Bu basit örneği düşünün (psql'de):
db = # SELECT zaman damgası '2012-03-05 20:00 +03 ';
timestamptz
------------------------
2012-03-05 18:00:00 +01
Cesur vurgu benim. Burada ne oldu? Girdi değişmezi için
rasgele bir saat dilimi sapması seçtim +3
. Postgres için bu UTC zaman damgasını girmenin birçok yolundan sadece biridir 2012-03-05 17:00:00
. Sorgunun sonucu, kış ve yaz aylarında ofseti olan testimde geçerli saat dilimi ayarı Viyana / Avusturya için görüntülenir : çünkü kışa düşer.+1
+2
2012-03-05 18:00:00+01
Postgres bu değerin nasıl girildiğini zaten unutmuş. Tek hatırladığı değer ve veri türüdür. Ondalık bir sayı gibi. numeric '003.4'
, numeric '3.40'
Ya numeric '+3.4'
- aynı iç değerindeki tüm sonucu.
AT TIME ZONE
Bu mantığı kavradığınızda, istediğiniz her şeyi yapabilirsiniz. Şimdi eksik olan tek şey, zaman damgası değişmez değerlerini belirli bir saat dilimine göre yorumlamak veya temsil etmek için bir araçtır. AT TIME ZONE
Yapı burada devreye giriyor. İki farklı kullanım durumu var. timestamptz
dönüştürülür timestamp
ve tam tersi.
UTC'yi girmek için timestamptz
2012-03-05 17:00:00+0
:
SELECT timestamp '2012-03-05 17:00:00' AT TIME ZONE 'UTC'
... şuna eşittir:
SELECT timestamptz '2012-03-05 17:00:00 UTC'
EST timestamp
(Doğu Standart Saati) ile aynı noktayı görüntülemek için :
SELECT timestamp '2012-03-05 17:00:00' AT TIME ZONE 'UTC' AT TIME ZONE 'EST'
Bu doğru, AT TIME ZONE 'UTC'
iki kez . Birincisi, timestamp
değeri türü döndüren (verilen) UTC zaman damgası olarak yorumlar timestamptz
. İkincisi ise dönüştürür timestamptz
için timestamp
verilen zaman diliminde 'EST' in - Ne zamandır bu eşsiz noktasında saat dilimi EST ekranlarda bir saat.
Örnekler
SELECT ts AT TIME ZONE 'UTC'
FROM (
VALUES
(1, timestamptz '2012-03-05 17:00:00+0')
, (2, timestamptz '2012-03-05 18:00:00+1')
, (3, timestamptz '2012-03-05 17:00:00 UTC')
, (4, timestamp '2012-03-05 11:00:00' AT TIME ZONE '+6')
, (5, timestamp '2012-03-05 17:00:00' AT TIME ZONE 'UTC')
, (6, timestamp '2012-03-05 07:00:00' AT TIME ZONE 'US/Hawaii') -- ①
, (7, timestamptz '2012-03-05 07:00:00 US/Hawaii') -- ①
, (8, timestamp '2012-03-05 07:00:00' AT TIME ZONE 'HST') -- ①
, (9, timestamp '2012-03-05 18:00:00+1') -- ② loaded footgun!
) t(id, ts);
Aynı UTC zaman damgasını taşıyan zaman damgası sütunlarına sahip 8 (veya 9) özdeş satırı döndürür 2012-03-05 17:00:00
. 9. sıra benim zaman dilimimde çalışıyor, ama kötü bir tuzak. Aşağıya bakınız.
Hawaii Hawaii saati için saat dilimi adı ve saat dilimi kısaltması içeren 6 - 8 numaralı satırlar DST'ye (yaz saati uygulaması) tabidir ve şu anda olmasa da farklılık gösterebilir. Gibi bir zaman dilimi adı 'US/Hawaii'
DST kurallarının ve tüm tarihsel vardiyaların otomatik olarak farkındayken, böyle bir kısaltma HST
sabit bir ofset için sadece aptal bir koddur. Yaz / standart süre için farklı bir kısaltma eklemeniz gerekebilir. Adı doğru yorumladığı herhangi belirli bir zaman diliminde de zaman damgası. Bir kısaltma ucuzdur, ancak verilen zaman damgası için doğru olanı olması gerekir:
Yaz Saati Uygulaması, insanlığın ortaya çıkardığı en parlak fikirler arasında değildir.
Foot Yüklü tabanca olarak işaretlenmiş Satır 9 benim için çalışıyor , ancak sadece tesadüflerle. Açık bir şekilde bir değişmez değeri kullanırsanız timestamp [without time zone]
, herhangi bir saat dilimi uzaklığı yoksayılır ! Yalnızca çıplak zaman damgası kullanılır. Daha sonra değer, timestamptz
sütun türüyle eşleşmesi için örnekte otomatik olarak zorlanır . Bu adım için, benim durumumda (Avrupa / Viyana) timezone
aynı saat dilimi olan geçerli oturumun ayarlandığı varsayılmaktadır +1
. Ama muhtemelen sizin durumunuzda değil - bu farklı bir değerle sonuçlanacaktır. Kısaca: timestamptz
Değişmez değerler yerleştirmeyin timestamp
veya saat dilimi farkını kaybedersiniz.
Sorularınız
Kullanıcı 17 Mart 2012 saat 19: 00'da bir zaman depolar. Saat dilimi dönüşümlerinin veya saat diliminin depolanmasını istemiyorum.
Zaman diliminin kendisi asla kaydedilmez. UTC zaman damgası girmek için yukarıdaki yöntemlerden birini kullanın.
Kullanıcıların belirtilen saat dilimini, kullanıcıların yerel saat dilimindeki geçerli saatten önce 'önce' veya 'sonra' almak için kullanıyorum.
Farklı saat dilimlerindeki tüm istemciler için tek bir sorgu kullanabilirsiniz.
Mutlak küresel zaman için:
SELECT * FROM tbl WHERE time_col > (now() AT TIME ZONE 'UTC')::time
Yerel saate göre zaman için:
SELECT * FROM tbl WHERE time_col > now()::time
Henüz arka plan bilgisinden sıkılmadınız mı? Kılavuzda daha fazlası var.