Bölge adı PostgreSQL hatasıyla “AT TIME ZONE”?


12

Bu stackoverflow soruya cevap ve garip sonuç bulundu:

 select * from  pg_timezone_names where name = 'Europe/Berlin' ;
     name      | abbrev | utc_offset | is_dst 
---------------+--------+------------+--------
 Europe/Berlin | CET    | 01:00:00   | f

ve sonraki sorgu

select id, 
  timestampwithtimezone, 
  timestampwithtimezone at time zone 'Europe/Berlin' as berlin, 
  timestampwithtimezone at time zone 'CET' as cet 
from data ;
 id  | timestampwithtimezone  |       berlin        |         cet         
 -----+------------------------+---------------------+---------------------
 205 | 2012-10-28 01:30:00+02 | 2012-10-28 01:30:00 | 2012-10-28 00:30:00
 204 | 2012-10-28 02:00:00+02 | 2012-10-28 02:00:00 | 2012-10-28 01:00:00
 203 | 2012-10-28 02:30:00+02 | 2012-10-28 02:30:00 | 2012-10-28 01:30:00
 202 | 2012-10-28 02:59:59+02 | 2012-10-28 02:59:59 | 2012-10-28 01:59:59
 106 | 2012-10-28 02:00:00+01 | 2012-10-28 02:00:00 | 2012-10-28 02:00:00

PostgreSQL 9.1.2 ve Ubuntu 12.04 kullanıyorum.
Sadece 8.2.11 sonucunun aynı olduğunu kontrol ettim.

Belgelere göre, isim veya kısaltma kullanmam önemli değil.

Bu bir hata mı?
Yanlış bir şey mi yapıyorum?
Birisi bu sonucu açıklayabilir mi?

EDIT CET'in Avrupa / Berlin olmadığı yorumu için.

Ben sadece pg_timezone_names değerleri seçiyorum.

select * from  pg_timezone_names  where abbrev ='CEST';
 name | abbrev | utc_offset | is_dst 
------+--------+------------+--------

ve

select * from  pg_timezone_names  where abbrev ='CET';
        name         | abbrev | utc_offset | is_dst 
---------------------+--------+------------+--------
 Africa/Tunis        | CET    | 01:00:00   | f
 Africa/Algiers      | CET    | 01:00:00   | f
 Africa/Ceuta        | CET    | 01:00:00   | f
 CET                 | CET    | 01:00:00   | f
 Atlantic/Jan_Mayen  | CET    | 01:00:00   | f
 Arctic/Longyearbyen | CET    | 01:00:00   | f
 Poland              | CET    | 01:00:00   | f
 .....

Kışın Avrupa / Berlin +01'dir. Yaz aylarında +02'dir.

EDIT2 2012-10-28'de saat dilimi yaz saatinden kış saatine 2: 00'da değişmiştir.
Bu iki kayıt Avrupa / Berlin'de aynı değere sahiptir:

204 | 2012-10-28 02:00:00+02 | 2012-10-28 02:00:00 | 2012-10-28 01:00:00
106 | 2012-10-28 02:00:00+01 | 2012-10-28 02:00:00 | 2012-10-28 02:00:00

Bu, büyük veri aralığı (yaz saati ve kış saati) için kısaltmalardan birini (CET veya CEST) kullanırsam sonuçların bazı kayıtlar için yanlış olacağını gösterir. 'Avrupa / Berlin' kullanırsam iyi olur.

Sistem saatini '2012-01-17' olarak değiştirdim ve pg_timezone_names de değişti.

select * from  pg_timezone_names  where name ='Europe/Berlin';
     name      | abbrev | utc_offset | is_dst 
---------------+--------+------------+--------
 Europe/Berlin | CEST   | 02:00:00   | t

1
2012-10-28 01:30:00CET değil, CEST olduğundan emin .
dezso

1
Gibi bildiğim kadarıyla CETolduğunu değil Europe/Berlin - en azından değil DST zamanlarda.
a_horse_with_no_name

Yanıtlar:


9

Aslında belgeler, saat dilimi adı ve kısaltmasının farklı davranacağını açıkça söylüyor.

Kısacası, bu kısaltmalar ve tam adlar arasındaki farktır: kısaltmalar her zaman UTC'den sabit bir ofseti temsil ederken, tam adların çoğu yerel bir gün ışığından yararlanma saati kuralı anlamına gelir ve bu nedenle iki olası UTC ofseti vardır. Referans

FWIW, aynı referans aynı zamanda

Yazım saatini saat dilimi ile kullanmanızı önermiyoruz (eski uygulamalar ve SQL standardına uyumluluk için PostgreSQL tarafından desteklenmesine rağmen).


6

Ve bu hala onun özü değil! Ben koştum çok benzer bir sorun bir süre önce.

Saat dilimi kısaltmalarının ana eksileri burada zaten sunulmuştur: DST'yi (yaz saati uygulaması) dikkate almazlar. En büyük profesyonel: basitlik, üstün performans sağlar . DST kurallarını hesaba katmak zaman dilimi adlarını yavaşlatmaktadır . Zaman dilimi kısaltmaları basit, sembolik zaman ofsetleridir, zaman dilimi adları sürekli değişen kurallara tabidir. SO ile ilgili bu cevapta karşılaştırmalar yaptım , fark dikkat çekicidir. Ancak bir kümeye uygulandığında, satır başına muhtemelen farklı DST durumunu (ve ayrıca tarihi farklılıkları) kapsayacak şekilde zaman dilimi adlarını kullanmak gerekir .

CET hakkında konuşuyoruz . Gerçekten zor kısmı "CET" sadece (açıkçası) bir zaman dilimi kısaltması değil, aynı zamanda bir zaman dilimi adı , en azından benim kurulum (PostgreSQL 9.1.6 yerel ayarlı Debian Squeeze "de_AT.UTF-8 ") ve şimdiye kadar gördüğüm diğer tüm kullanıcılar. Postgres varsa, temel işletim sisteminin yerel bilgilerini kullandığı için bu ayrıntılardan bahsediyorum.

Kendin için gör:

SELECT * FROM pg_timezone_names WHERE name = 'CET';

SELECT * FROM pg_timezone_abbrevs WHERE abbrev = 'CET';

SQL Fiddle.

Postgres kısaltmayı tam adıyla alır. Bu nedenle, saat dilimi adlarında CET bulduğum halde , ifade '2012-01-18 01:00 CET'::timestamptz, saat dilimi kısaltmaları için kurnazca farklı kurallara göre yorumlanır .

Eğer bu yüklü bir tabanca değilse ne olduğunu bilmiyorum.

Belirsizliklerden kaçınmak için, zaman dilimi adı 'Europe / Berlin' (ya da benim durumumda 'Europe / Vienna') ile gidin - ki bu tarihsel farklılıklar dışında etkili bir şekilde aynıdır). Yukarıda bahsettiğim yakından ilişkili sorunun altındaki konu hakkında daha fazla bilgi edinin .

Kapanışta, DST'nin moronik konsepti için derinden hissettiğimi duymak isterim. Varoluştan uzaklaştırılmalı ve bir daha asla konuşulmamalıdır.


3

Şunu bir kontrol et:

select  
    '2012-10-28 02:30:00+02'::timestamp with time zone at time zone 'Europe/Berlin' as berlin,
    '2012-10-28 02:30:00+02'::timestamp with time zone at time zone 'CET' as cet,
    '2012-10-28 02:30:00+02'::timestamp with time zone at time zone 'CEST' as cest

+02 Berlin'deki CEST, CET değil.

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.