PostgreSQL'de UTC'de geçerli saati varsayılan değer olarak kullanma


172

Ben TIMESTAMP WITHOUT TIME ZONEtürü bir sütun var ve UTC'de şimdiki zaman için varsayılan var istiyorum. UTC'de şu anki saati almak kolaydır:

postgres=# select now() at time zone 'utc';
          timezone          
----------------------------
 2013-05-17 12:52:51.337466
(1 row)

Bir sütun için geçerli zaman damgasını kullanırken:

postgres=# create temporary table test(id int, ts timestamp without time zone default current_timestamp);
CREATE TABLE
postgres=# insert into test values (1) returning ts;
             ts             
----------------------------
 2013-05-17 14:54:33.072725
(1 row)

Ancak bu yerel saati kullanır. Bunu UTC'ye zorlamaya çalışmak bir sözdizimi hatasına neden olur:

postgres=# create temporary table test(id int, ts timestamp without time zone default now() at time zone 'utc');
ERROR:  syntax error at or near "at"
LINE 1: ...int, ts timestamp without time zone default now() at time zo...

Yanıtlar:


299

Bir fonksiyona bile gerek yoktur. Parantezleri varsayılan ifadenin etrafına koymanız yeterlidir:

create temporary table test(
    id int, 
    ts timestamp without time zone default (now() at time zone 'utc')
);

2
Şimdi sorgular yazarken now_utc () gibi bir funciton görebilirsiniz
misaxi

Bu, zaman bir saat geri döndüğünde bile işe yarar - now (), UTC'den farkı bilen bir zaman damgası döndürür.
Clay Lenhart

1
FWIW, PostgreSQL 11.5 bu sorguyu çalıştıran: ALTER TABLE testcase_result ADD COLUMN date_created TIMESTAMP WITHOUT TIME ZONE DEFAULT (NOW() AT TIME ZONE "UTC") NOT NULL;başarısız: ERROR: column "UTC" does not exist. Tamamen küçük olduğundan emin olun 'utc'.
code_dredd

2
Düzeltme: 'utc'Dize ayrıca çift tırnaklı değil tek tırnaklı olmalıdır.
code_dredd

56

Yine başka bir çözüm:

timezone('utc', now())

26

Bir işlevde sarın:

create function now_utc() returns timestamp as $$
  select now() at time zone 'utc';
$$ language sql;

create temporary table test(
  id int,
  ts timestamp without time zone default now_utc()
);

16

Ne dersin

now()::timestamp

Diğer zaman damganız saat dilimi içermiyorsa, bu yayın geçerli saat için eşleşen "zaman dilimi olmayan zaman damgası" türünü verir.

Yine de başkalarının bu seçenek hakkında ne düşündüğünü okumak istiyorum. Hala bu "zaman dilimi" ile / zaman dilimi olmayan şeyleri anlamama güvenmiyorum.

EDIT: Michael Ekoka'nın yorumunu buraya ekleyerek önemli bir noktayı açıklığa kavuşturuyor:

Uyarı. Soru, saat dilimini saklamayan bir zaman damgası sütunu için UTC'de varsayılan zaman damgası oluşturmakla ilgilidir (belki de tüm zaman damgalarınızın aynı şeyi paylaştığını biliyorsanız zaman dilimini depolamanıza gerek yoktur). Çözümünüzün yaptığı şey, yerel bir zaman damgası oluşturmak (çoğu insan için mutlaka UTC'ye ayarlanmayacaktır) ve saf bir zaman damgası (zaman dilimini belirtmeyen) olarak saklamaktır.


Bu ilginç bir hile ama bu davranışın farkında değilseniz karışıklığa neden olabilir. Kabul edilen cevap, eylem ve istenen sonuç üzerinde berraktır. Fonksiyonu ile aynı ama DBs fonksiyonları uzak kalmak ....
Frank V

benim seçenek o db içine yerel datetime oluşturur
VelikiiNehochuha

Uyarı. Soru, saat dilimini saklamayan bir zaman damgası sütunu için UTC'de varsayılan zaman damgası oluşturmakla ilgilidir (belki de tüm zaman damgalarınızın aynı şeyi paylaştığını biliyorsanız zaman dilimini depolamanıza gerek yoktur). Çözümünüzün yaptığı şey, yerel bir zaman damgası oluşturmak (çoğu insan için mutlaka UTC'ye ayarlanmayacaktır) ve saf bir zaman damgası (zaman dilimini belirtmeyen) olarak saklamaktır.
Michael Ekoka

@MichaelEkoka Cevabınıza yorumunuzu ekledim - lütfen devam edin ve isterseniz düzenleyin. Çok açık bir şekilde açıklıyorsunuz. Teşekkürler!
Risadinha

Uyarı : saat dilimi alanına sahip bir zaman damgası, makul varsayımın aksine saat dilimini depolamaz. Aşağıdaki bağlantıya bakın ve sayfada UTC için arama yapın. Girişte, saat dilimli bir zaman damgası gelen değeri utc'ye dönüştürür ve bu değeri ZAMAN YOKU BÖLGESİ VEYA OFSET BİLGİSİ OLMADAN depolar . Çıktıda, saklanan utc değeri, varsa istemcinin saat dilimi kullanılarak yerel bir saate dönüştürülür. Bu tür, sorgu zamanında değer dönüşümü ile ilgilidir. Bunu bir zaman diliminden depolayıp farklı bir zaman dilimi arasından seçerek test etmelisiniz. postgresql.org/docs/11/datatype-datetime.html
Tom

7

Bunlar 2 eşdeğer çözümdür:

(Aşağıdaki kodda, sen değiştirmesi gerekir 'UTC'için bölge ve now()için zaman damgası )

  1. timestamp AT TIME ZONE zone - SQL standardına uygun
  2. timezone(zone, timestamp) - tartışmasız daha okunabilir

Saat dilimi (bölge, zaman damgası) işlevi, SQL uyumlu yapı zaman damgası AT TIME ZONE bölgesine eşdeğerdir.


Açıklama:

  • bölge , metin dizesi (ör. 'UTC') veya aralık (ör. INTERVAL '-08:00') olarak belirtilebilir - işte kullanılabilir tüm saat dilimlerinin listesi
  • zaman damgası , zaman damgası türünün herhangi bir değeri olabilir
  • now()veritabanınızın varsayılan saat dilimi (ör. ) eklenmiş olarak zaman damgası türünde bir değer döndürür (tam da ihtiyacımız olan şey 2018-11-11T12:07:22.3+05:00).
  • timezone('UTC', now())şimdiki zamanımızı ( zaman dilimi ile zaman damgası türünde ) saat diliminin zaman dilimi eşdeğerine çevirir UTC.
    Örneğin SELECT timestamp with time zone '2020-03-16 15:00:00-05' AT TIME ZONE 'UTC'geri dönecek 2020-03-16T20:00:00Z.

Dokümanlar: timezone ()


1
Bunları özetlediğiniz için teşekkürler. Küçük harf sürümünü kullandım at timezone 'utc've bu PostgreSQL kurulumumla çalışmadı. Büyük harf kullanma sorunu çözdü
Geradlus_RU

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.