“AT TIME ZONE” dengan nama zona PostgreSQL bug?

12

Saya menjawab pertanyaan stackoverflow ini dan menemukan hasil yang aneh:

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

dan permintaan selanjutnya

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

Saya menggunakan PostgreSQL 9.1.2 dan ubuntu 12.04.
Hanya memeriksa bahwa pada hasil 8.2.11 adalah sama.

Menurut dokumentasi , tidak masalah jika saya menggunakan nama atau singkatan.

Apakah ini bug?
Apakah saya melakukan sesuatu yang salah?
Adakah yang bisa menjelaskan hasil ini?

EDIT Untuk komentar bahwa CET bukan Eropa / Berlin.

Saya hanya memilih nilai dari pg_timezone_names.

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

dan

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

Selama musim dingin Eropa / Berlin adalah +01. Selama musim panas itu +02.

EDIT2 Pada 2012-10-28 zona waktu telah berubah dari waktu musim panas ke waktu musim dingin pada pukul 2:00.
Dua catatan ini memiliki nilai yang sama di Eropa / Berlin:

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

Ini menunjukkan bahwa jika saya menggunakan salah satu singkatan (CET atau CEST) untuk rentang data besar (waktu musim panas dan musim dingin) hasilnya akan salah untuk beberapa rekaman. Akan baik jika saya menggunakan 'Eropa / Berlin'.

Saya mengubah waktu sistem menjadi '2012-01-17' dan pg_timezone_names telah berubah juga.

select * from  pg_timezone_names  where name ='Europe/Berlin';
     name      | abbrev | utc_offset | is_dst 
---------------+--------+------------+--------
 Europe/Berlin | CEST   | 02:00:00   | t
sufleR
sumber
1
Sangat yakin bahwa itu 2012-10-28 01:30:00adalah CEST, bukan CET.
dezso
1
Sejauh yang saya tahu CETadalah tidak Europe/Berlin - setidaknya tidak selama DST kali.
a_horse_with_no_name

Jawaban:

9

Sebenarnya, dokumentasi mengatakan dengan jelas bahwa nama zona waktu dan singkatan akan berperilaku berbeda.

Singkatnya, ini adalah perbedaan antara singkatan dan nama lengkap: singkatan selalu mewakili offset tetap dari UTC, sedangkan sebagian besar nama lengkap menyiratkan aturan waktu-penghematan waktu lokal, dan memiliki dua kemungkinan offset UTC. Referensi

FWIW, referensi yang sama juga mengatakan

Kami tidak merekomendasikan penggunaan tipe waktu dengan zona waktu (meskipun didukung oleh PostgreSQL untuk aplikasi lawas dan untuk kepatuhan dengan standar SQL).

Mike Sherrill 'Cat Recall'
sumber
6

Dan itu masih bukan intinya! Saya mengalami masalah yang sangat mirip beberapa waktu lalu.

Kontra utama dari singkatan zona waktu telah disajikan di sini: mereka tidak memperhitungkan DST (waktu musim panas). Pro utama: kesederhanaan menghasilkan kinerja yang unggul . Mempertimbangkan aturan DST membuat nama zona waktu lebih lambat dibandingkan. Singkatan zona waktu sederhana, offset waktu simbolis, nama zona waktu tunduk pada seperangkat aturan yang terus berubah. Saya menjalankan tolok ukur dalam jawaban terkait pada SO ini , perbedaannya luar biasa. Tetapi ketika diterapkan pada himpunan, biasanya diperlukan untuk menggunakan nama zona waktu untuk mencakup kemungkinan status DST berbeda per baris (dan juga perbedaan historis).

Kita berbicara tentang CET . Bagian yang sulit adalah bahwa "CET" tidak hanya (jelas) sebuah singkatan zona waktu , itu adalah juga sebuah nama zona waktu , setidaknya menurut instalasi saya (PostgreSQL 9.1.6 pada Squeeze Debian dengan lokal "de_AT.UTF-8 ") dan semua yang saya lihat sejauh ini. Saya menyebutkan perincian ini, karena Postgres menggunakan informasi lokal dari OS yang mendasarinya jika tersedia.

Lihat diri mu sendiri:

SELECT * FROM pg_timezone_names WHERE name = 'CET';

SELECT * FROM pg_timezone_abbrevs WHERE abbrev = 'CET';

SQL Fiddle.

Postgres memilih singkatan dari nama lengkap. Jadi, meskipun saya menemukan CET dalam nama zona waktu , ungkapan '2012-01-18 01:00 CET'::timestamptztersebut ditafsirkan menurut aturan yang agak berbeda untuk singkatan zona waktu .

Jika itu bukan footgun yang dimuat, saya tidak tahu apa itu.

Untuk menghindari ambiguitas, gunakan nama zona waktu 'Eropa / Berlin' (atau 'Eropa / Wina' dalam kasus saya - yang secara efektif sama, kecuali untuk perbedaan historis). Temukan detail lebih lanjut tentang topik di bawah pertanyaan terkait erat yang saya sebutkan di atas .

Sebagai penutup, saya ingin menyuarakan rasa jijik saya yang dalam terhadap konsep tolol DST. Itu harus dihilangkan dari keberadaan dan tidak pernah dibicarakan lagi.

Erwin Brandstetter
sumber
3

Periksa ini:

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 adalah CEST di Berlin, bukan CET.

dezso
sumber