PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

PostgreSQL salah mengonversi dari stempel waktu tanpa zona waktu ke stempel waktu dengan zona waktu

Hal-hal penting yang harus dipahami

timestamp without time zone AT TIME ZONE menafsirkan ulang sebuah timestamp berada di zona waktu itu untuk tujuan mengubahnya menjadi UTC .

timestamp with time zone AT TIME ZONE mengkonversi sebuah timestamptz menjadi timestamp pada zona waktu yang ditentukan.

PostgreSQL menggunakan zona waktu ISO-8601, yang menentukan bahwa timur Greenwich adalah positif ... kecuali jika Anda menggunakan penentu zona waktu POSIX, dalam hal ini mengikuti POSIX. Kegilaan pun terjadi.

Mengapa yang pertama menghasilkan hasil yang tidak terduga

Stempel waktu dan zona waktu dalam SQL mengerikan. Ini:

select '2011-12-30 00:30:00'::timestamp without time zone AT TIME ZONE 'EST5EDT';

menginterpretasikan literal yang tidak diketahui jenisnya '2011-12-30 00:30:00' sebagai timestamp without time zone , yang diasumsikan Pg berada di TimeZone lokal kecuali jika diberitahu sebaliknya. Saat Anda menggunakan AT TIME ZONE , itu (sesuai spesifikasi) diinterpretasikan ulang sebagai timestamp with time zone di zona waktu EST5EDT kemudian disimpan sebagai waktu absolut dalam UTC - jadi diubah dari EST5EDT ke UTC, yaitu offset zona waktu dikurangi . x - (-5) adalah x + 5 .

Stempel waktu ini, disesuaikan dengan penyimpanan UTC, kemudian disesuaikan untuk server Anda TimeZone pengaturan untuk tampilan sehingga ditampilkan dalam waktu lokal.

Jika Anda ingin mengatakan "Saya memiliki stempel waktu ini dalam waktu UTC, dan ingin melihat waktu lokal yang setara dalam EST5EDT", jika Anda ingin independen dari pengaturan TimeZone server, Anda perlu menulis sesuatu seperti:

select TIMESTAMP '2011-12-30 00:30:00' AT TIME ZONE 'UTC'
       AT TIME ZONE 'EST5EDT';

Ini mengatakan "Stempel waktu yang diberikan 2011-12-30 00:30:00, perlakukan itu sebagai stempel waktu di UTC saat mengonversi ke stempel waktu, lalu ubah stempel waktu itu ke waktu lokal di EST5EDT".

Mengerikan, bukan? Saya ingin memberi perusahaan berbicara siapa pun yang memutuskan semantik gila AT TIME ZONE - seharusnya benar-benar seperti timestamp CONVERT FROM TIME ZONE '-5' dan timestamptz CONVERT TO TIME ZONE '+5' . Juga, timestamp with time zone harus benar-benar membawa zona waktunya, tidak disimpan dalam UTC dan dikonversi secara otomatis ke waktu lokal.

Mengapa yang kedua berhasil (selama TimeZone =UTC)

Versi "berfungsi" asli Anda:

select '2011-12-30 00:30:00' AT TIME ZONE 'EST5EDT';

hanya akan benar jika TimeZone disetel ke UTC, karena pemeran text-to-timestamptz mengasumsikan TimeZone saat tidak ditentukan.

Mengapa yang ketiga berhasil

Dua masalah membatalkan satu sama lain.

Versi lain yang tampaknya berfungsi adalah TimeZone independen, tetapi hanya berfungsi karena dua masalah membatalkan sendiri. Pertama, seperti yang dijelaskan di atas, timestamp without time zone AT TIME ZONE menafsirkan ulang stempel waktu berada di zona waktu tersebut untuk konversi ke stempel waktu UTC; ini secara efektif mengurangi offset zona waktu.

Namun, untuk alasan yang tidak saya ketahui, PostgreSQL menggunakan stempel waktu dengan tanda kebalikan dari apa yang biasa saya lihat di sebagian besar tempat. Lihat dokumentasi:

Masalah lain yang perlu diingat adalah bahwa dalam nama zona waktu POSIX, offset positif digunakan untuk lokasi di sebelah barat Greenwich. Di tempat lain, PostgreSQL mengikuti konvensi ISO-8601 bahwa offset zona waktu positif berada di sebelah timur Greenwich.

Ini berarti bahwa EST5EDT sama dengan +5 , bukan -5 . Itulah mengapa ini berhasil:karena Anda mengurangi offset tz bukan menambahkannya, tetapi Anda mengurangi offset yang dinegasikan!

Yang Anda perlukan untuk memperbaikinya adalah:

select TIMESTAMP '2011-12-30 00:30:00' AT TIME ZONE 'UTC'
       AT TIME ZONE '+5';



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Desain database temporal, dengan twist (live vs draft rows)

  2. 5 Alat Pemantauan Kueri PostgreSQL Teratas

  3. PostgreSQL salah mengonversi dari stempel waktu tanpa zona waktu ke stempel waktu dengan zona waktu

  4. Bagaimana saya harus mengimpor data dari CSV ke tabel Postgres menggunakan pgAdmin 3?

  5. Tidak dapat menghubungkan postgreSQL dengan psycopg2