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

Mewakili waktu mendatang di PostgreSQL

Sepertinya Anda ingin menyimpan waktu setempat sehubungan dengan zona waktu tertentu. Dalam hal ini, simpan timestamp (tanpa zona waktu) dan timezone di kolom terpisah.

Misalnya, Anda ingin merekam peristiwa yang akan terjadi pada pukul 10 pagi pada tanggal 26 Februari 2030 di Chicago dan harus pada pukul 10 pagi waktu setempat terlepas dari aturan zona waktu yang berlaku pada tanggal tersebut.

Jika database menyimpan stempel waktu tanpa zona waktu:

unutbu=# select '2030-02-26 10:00:00'::timestamp as localtime, 'America/Chicago' AS tzone;
+---------------------+-----------------+
|      localtime      |      tzone      |
+---------------------+-----------------+
| 2030-02-26 10:00:00 | America/Chicago |
+---------------------+-----------------+

Kemudian nanti, Anda dapat menemukan tanggal UTC acara menggunakan

unutbu=# select '2030-02-26 10:00:00'::timestamp AT TIME ZONE 'America/Chicago' AT TIME ZONE 'UTC';
+---------------------+
|      timezone       |
+---------------------+
| 2030-02-26 16:00:00 |
+---------------------+

Kueri mengembalikan tanggal waktu UTC, 2030-02-26 16:00:00 , yang sesuai dengan 2030-02-26 10:00:00 waktu setempat di Chicago.

Menggunakan AT TIME ZONE menunda penerapan aturan zona waktu ke saat kueri dibuat alih-alih saat timestamptz dimasukkan.

Menggunakan AT TIME ZONE pada timestamp melokalkan datetime ke zona waktu tertentu, tetapi melaporkan datetime di zona waktu pengguna .Menggunakan AT TIME ZONE pada timestamptz mengonversi datetime ke zona waktu tertentu, lalu menghapus offset, sehingga mengembalikan timestamp .Di atas, AT TIME ZONE digunakan dua kali:pertama untuk melokalkan timestamp dan selanjutnya untuk mengonversi timestamptz . yang dikembalikan ke zona waktu baru (UTC). Hasilnya adalah timestamp di UTC.

Berikut ini contohnya, mendemonstrasikan AT TIME ZONE perilaku pada timestamp s:

unutbu=# SET timezone = 'America/Chicago';
unutbu=# SELECT '2030-02-26 10:00:00'::timestamp AT TIME ZONE 'America/Chicago';
+------------------------+
|        timezone        |
+------------------------+
| 2030-02-26 10:00:00-06 |
+------------------------+

unutbu=# SET timezone = 'America/Los_Angeles';
unutbu=# SELECT '2030-02-26 10:00:00'::timestamp AT TIME ZONE 'America/Chicago';
+------------------------+
|        timezone        |
+------------------------+
| 2030-02-26 08:00:00-08 |
+------------------------+

2030-02-26 10:00:00-06 dan 2030-02-26 08:00:00-08 adalah tanggal yang sama tetapi dilaporkan dalam zona waktu pengguna yang berbeda. Ini menunjukkan pukul 10 pagi di Chicago adalah pukul 8 pagi di Los Angeles (menggunakan definisi zona waktu saat ini):

unutbu=# SELECT '2030-02-26 10:00:00-06'::timestamptz AT TIME ZONE 'America/Los_Angeles';
+---------------------+
|      timezone       |
+---------------------+
| 2030-02-26 08:00:00 |
+---------------------+

Alternatif untuk menggunakan AT TIME ZONE dua kali adalah menyetel zona waktu pengguna ke UTC . Kemudian Anda dapat menggunakan

select localtime AT TIME ZONE tzone

Perhatikan bahwa jika dilakukan dengan cara ini, timestamptz dikembalikan sebagai ganti timestamp .

Berhati-hatilah karena menyimpan waktu lokal dapat menjadi masalah karena mungkin ada waktu yang tidak ada dan waktu yang ambigu. Misalnya, 2018-03-11 02:30:00 adalah waktu lokal yang tidak ada di America/Chicago . Postgresql menormalkan waktu lokal yang tidak ada dengan menganggapnya mengacu pada waktu yang sesuai setelah Daylight Savings Time (DST) dimulai (seolah-olah seseorang lupa menyetel jam mereka ke depan):

unutbu=# select '2018-03-11 02:30:00'::timestamp AT TIME ZONE 'America/Chicago' AT TIME ZONE 'UTC';
+---------------------+
|      timezone       |
+---------------------+
| 2018-03-11 08:30:00 |
+---------------------+
(1 row)

unutbu=# select '2018-03-11 03:30:00'::timestamp AT TIME ZONE 'America/Chicago' AT TIME ZONE 'UTC';
+---------------------+
|      timezone       |
+---------------------+
| 2018-03-11 08:30:00 |
+---------------------+
(1 row)

Contoh waktu lokal yang ambigu adalah 2018-11-04 01:00:00 di America/Chicago . Ini terjadi dua kali karena DST. Postgresql menyelesaikan ambiguitas ini dengan memilih waktu nanti, setelah DST berakhir:

unutbu=# select '2018-11-04 01:00:00'::timestamp AT TIME ZONE 'America/Chicago' AT TIME ZONE 'UTC';
+---------------------+
|      timezone       |
+---------------------+
| 2018-11-04 07:00:00 |
+---------------------+

Perhatikan bahwa ini berarti tidak ada cara untuk merujuk ke 2018-11-04 06:00:00 UTC dengan menyimpan waktu lokal di America/Chicago zona waktu:

unutbu=# select '2018-11-04 00:59:59'::timestamp AT TIME ZONE 'America/Chicago' AT TIME ZONE 'UTC';
+---------------------+
|      timezone       |
+---------------------+
| 2018-11-04 05:59:59 |
+---------------------+


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Kesalahan dalam LINQ (kolom tidak ada) saat menggunakan Entity Framework

  2. Kesalahan saat menjalankan python manage.py syncdb secara lokal, tetapi tidak ada kesalahan saat menjalankan perintah yang sama melalui Heroku

  3. SUM() Fungsi di PostgreSQL

  4. Beberapa ide tentang pengumpulan sumber daya tingkat rendah di PostgreSQL

  5. Pernyataan yang Disiapkan Sudah Ada