Apakah nilai stempel waktu disimpan secara berbeda di PostgreSQL saat tipe data WITH TIME ZONE
dibandingkan WITHOUT TIME ZONE
? Bisakah perbedaan diilustrasikan dengan kasus uji sederhana?
postgresql
types
timestamp
timezone
Larsenal
sumber
sumber
Jawaban:
Perbedaannya tercakup pada dokumentasi PostgreSQL untuk tipe tanggal / waktu . Ya, perawatan
TIME
atauTIMESTAMP
berbeda antara satuWITH TIME ZONE
atauWITHOUT TIME ZONE
. Itu tidak mempengaruhi bagaimana nilai-nilai disimpan; itu mempengaruhi bagaimana mereka ditafsirkan.Efek zona waktu pada tipe data ini dicakup secara khusus dalam dokumen. Perbedaan muncul dari apa yang dapat diketahui oleh sistem tentang nilai:
Dengan zona waktu sebagai bagian dari nilai, nilai dapat diberikan sebagai waktu lokal di klien.
Tanpa zona waktu sebagai bagian dari nilai, zona waktu default yang jelas adalah UTC, sehingga diberikan untuk zona waktu itu.
Perilaku berbeda tergantung pada setidaknya tiga faktor:
WITH TIME ZONE
atauWITHOUT TIME ZONE
) dari nilai.Berikut adalah contoh yang mencakup kombinasi faktor-faktor tersebut:
sumber
timestamp with time zone
dantimestamp without time zone
, di Postgres * tidak benar - benar menyimpan informasi zona waktu. Anda dapat mengkonfirmasi ini dengan melihat sekilas pada halaman dokumen tipe data: Kedua jenis ini menggunakan jumlah oktet yang sama dan memiliki rentang nilai penyimpanan, sehingga tidak ada ruang untuk menyimpan info zona waktu. Teks halaman mengkonfirmasi ini. Sesuatu yang keliru: "tanpa tz" berarti "abaikan offset saat memasukkan data" dan "dengan tz" berarti "gunakan offset untuk menyesuaikan ke UTC".Saya mencoba menjelaskannya lebih dimengerti daripada dokumentasi PostgreSQL yang dimaksud.
Baik
TIMESTAMP
varian menyimpan zona waktu (atau offset), meskipun apa nama menyarankan. Perbedaannya terletak pada interpretasi data yang disimpan (dan dalam aplikasi yang dimaksud), bukan dalam format penyimpanan itu sendiri:TIMESTAMP WITHOUT TIME ZONE
menyimpan waktu tanggal lokal (alias. tanggal kalender dinding dan waktu jam dinding). Zona waktunya tidak ditentukan sejauh yang PostgreSQL tahu (meskipun aplikasi Anda mungkin tahu apa itu). Karenanya, PostgreSQL tidak melakukan konversi terkait zona waktu pada input atau output. Jika nilai dimasukkan ke dalam basis data sebagai'2011-07-01 06:30:30'
, maka tidak ada mater di zona waktu yang Anda tampilkan nanti, itu masih akan mengatakan tahun 2011, bulan 07, hari 01, 06 jam, 30 menit, dan 30 detik (dalam beberapa format). Juga, setiap offset atau zona waktu yang Anda tentukan dalam input diabaikan oleh PostgreSQL, jadi'2011-07-01 06:30:30+00'
dan'2011-07-01 06:30:30+05'
sama dengan adil'2011-07-01 06:30:30'
. Untuk pengembang Java: analog denganjava.time.LocalDateTime
.TIMESTAMP WITH TIME ZONE
menyimpan titik pada garis waktu UTC. Kelihatannya (berapa jam, menit, dll.) Tergantung pada zona waktu Anda, tetapi selalu mengacu pada instan "fisik" yang sama (seperti saat peristiwa fisik aktual). Input secara internal dikonversi ke UTC, dan begitulah disimpan. Untuk itu, offset input harus diketahui, jadi ketika input tersebut tidak mengandung offset atau zona waktu eksplisit (seperti'2011-07-01 06:30:30'
) itu dianggap berada di zona waktu saat ini dari sesi PostgreSQL, jika tidak, zona offset atau zona waktu yang ditentukan secara eksplisit digunakan (seperti dalam'2011-07-01 06:30:30+05'
). Outputnya ditampilkan dikonversi ke zona waktu saat ini dari sesi PostgreSQL. Untuk pengembang Java: Ini analog denganjava.time.Instant
(dengan resolusi lebih rendah), tetapi dengan JDBC dan JPA 2.2 Anda seharusnya memetakannya kejava.time.OffsetDateTime
(atau kejava.util.Date
ataujava.sql.Timestamp
tentu saja).Ada yang mengatakan bahwa kedua
TIMESTAMP
variasi menyimpan waktu tanggal UTC. Agak, tapi itu membingungkan menurut saya.TIMESTAMP WITHOUT TIME ZONE
disimpan sepertiTIMESTAMP WITH TIME ZONE
, yang diberikan dengan zona waktu UTC terjadi untuk memberikan tahun yang sama, bulan, hari, jam, menit, detik, dan mikrodetik seperti yang ada di waktu-tanggal lokal. Tapi itu tidak dimaksudkan untuk mewakili titik pada garis waktu yang menurut interpretasi UTC, itu hanya cara bidang tanggal waktu setempat dikodekan. (Ini adalah beberapa titik pada garis waktu, karena zona waktu sebenarnya bukan UTC; kami tidak tahu apa itu.)sumber
TIMESTAMP WITH TIME ZONE
aInstant
. Keduanya mewakili titik pada timeline di UTC.Instant
lebih disukai, menurut saya, lebihOffsetDateTime
karena lebih mendokumentasikan diri sendiri: ATIMESTAMP WITH TIME ZONE
selalu diambil dari database sebagai UTC, danInstant
selalu dalam UTC sehingga cocok secara alami, sementara yangOffsetDateTime
dapat membawa offset lainnya.OffsetDateTime
sebagai tipe Java yang dipetakan. Saya tidak yakin apakahInstance
masih didukung di suatu tempat secara tidak resmi.'2011-07-01 06:30:30+00'
dan'2011-07-01 06:30:30+05'
diabaikan tapi saya bisa lakukaninsert into test_table (date) values ('2018-03-24T00:00:00-05:00'::timestamptz);
dan itu akan mengubahnya menjadi utc dengan benar. di mana tanggal adalah timestamp tanpa zona waktu. Saya mencoba memahami apa nilai utama cap waktu dengan zona waktu dan mengalami masalah.::timestamptz
. Dengan itu Anda mengonversi string menjadiTIMESTAMP WITH TIME ZONE
, dan saat itu akan dikonversi lebih jauhWITHOUT TIME ZONE
, yang akan menyimpan hari "kalender dinding" dan waktu jam dinding instan itu seperti yang terlihat dari zona waktu sesi Anda (yang mungkin UTC). Masih hanya akan menjadi timestamp lokal dengan offset yang tidak ditentukan (tanpa zona).Berikut adalah contoh yang dapat membantu. Jika Anda memiliki stempel waktu dengan zona waktu, Anda dapat mengubah stempel waktu itu menjadi zona waktu lainnya. Jika Anda belum memiliki zona waktu basis, zona waktu itu tidak akan dikonversi dengan benar.
Keluaran:
sumber
timestamp
dantimestamptz
artinya.timestamptz
berarti titik absolut dalam waktu (UTC) sedangkantimestamp
menunjukkan apa yang ditunjukkan jam di zona waktu tertentu. Jadi, ketika mengkonversitimestamptz
ke zona waktu Anda bertanya apa yang ditunjukkan jam di New York pada titik waktu absolut ini? sedangkan ketika "mengubah" atimestamp
, Anda bertanya apa titik absolut waktu ketika jam di New York menunjukkan x?AT TIME ZONE
membangun adalah otak teaser sendiri, bahkan jika Anda sudah memahamiWITH
vsWITHOUT TIME ZONE
jenis. Jadi itu pilihan yang aneh untuk menjelaskannya. (: (AT TIME ZONE
mengubahWITH TIME ZONE
cap waktu menjadiWITHOUT TIME ZONE
cap waktu, dan sebaliknya ... tidak terlalu jelas.)now()::timestamp AT TIME ZONE 'CST'
tidak masuk akal, kecuali Anda apa pada jam berapa CST 'zona waktu akan menunjukkan waktu bahwa jam lokal Anda saat ini menunjukkan