Dalam postgres, timestamp with time zone
dapat disingkat sebagai timestamptz
, dan timestamp without time zone
sebagai timestamp
. Saya akan menggunakan nama jenis yang lebih pendek untuk kesederhanaan.
Mendapatkan cap waktu Unix dari postgres timestamptz
like now()
itu sederhana, seperti yang Anda katakan, cukup:
select extract(epoch from now());
Itu benar-benar semua yang perlu Anda ketahui tentang mendapatkan waktu absolut dari jenis apa pun timestamptz
, termasuk now()
.
Hal-hal hanya menjadi rumit ketika Anda memiliki timestamp
bidang.
Ketika Anda memasukkan timestamptz
data seperti itu now()
ke bidang itu, pertama-tama data itu akan dikonversi ke zona waktu tertentu (baik secara eksplisit dengan at time zone
atau dengan mengonversi ke zona waktu sesi) dan informasi zona waktu dibuang . Itu tidak lagi mengacu pada waktu absolut. Inilah sebabnya mengapa Anda biasanya tidak ingin menyimpan cap waktu seperti timestamp
dan biasanya menggunakan timestamptz
- mungkin sebuah film dirilis pada pukul 6 sore pada tanggal tertentu di setiap zona waktu , itulah jenis kasus penggunaan.
Jika Anda hanya pernah bekerja di zona waktu tunggal, Anda mungkin lolos dengan (mis) menggunakan timestamp
. Konversi kembali ke timestamptz
cukup pintar untuk mengatasi DST, dan cap waktu dianggap, untuk tujuan konversi, berada di zona waktu saat ini. Berikut ini contoh untuk GMT / BST:
select '2011-03-27 00:59:00.0+00'::timestamptz::timestamp::timestamptz
, '2011-03-27 01:00:00.0+00'::timestamptz::timestamp::timestamptz;
/*
|timestamptz |timestamptz |
|:---------------------|:---------------------|
|2011-03-27 00:59:00+00|2011-03-27 02:00:00+01|
*/
DBFiddle
Tapi, perhatikan perilaku membingungkan berikut:
set timezone to 0;
values(1, '1970-01-01 00:00:00+00'::timestamp::timestamptz)
, (2, '1970-01-01 00:00:00+02'::timestamp::timestamptz);
/*
|column1|column2 |
|------:|:---------------------|
| 1|1970-01-01 00:00:00+00|
| 2|1970-01-01 00:00:00+00|
*/
DBFiddle
Ini karena :
PostgreSQL tidak pernah memeriksa konten string literal sebelum menentukan jenisnya, dan karenanya akan memperlakukan keduanya [...] sebagai timestamp tanpa zona waktu. Untuk memastikan literal diperlakukan sebagai timestamp dengan zona waktu, berikan tipe eksplisit yang benar ... Dalam literal yang telah ditentukan sebagai timestamp tanpa zona waktu, PostgreSQL diam-diam akan mengabaikan indikasi zona waktu apa pun
SELECT FLOOR(EXTRACT(epoch FROM NOW())*1000);
tidak mengembalikan stempel waktu yang benar karena konversi zona waktu postgres membuang informasi zona waktu dari hasilnya:
setelah itu, ekstrak melihat stempel waktu tanpa zona waktu dan menganggapnya sebagai waktu lokal (meskipun sebenarnya sudah utc).
Cara yang benar adalah:
Di baris terakhir yang pertama
at time zone
melakukan konversi, yang kedua memberikan zona waktu baru ke hasilnya.sumber