Apa kasus penggunaan yang valid untuk menggunakan TIMESTAMP TANPA ZONA WAKTU?

41

Ada jawaban yang panjang dan cukup menjelaskan tentang perbedaan di antara keduanya

  • TIMESTAMP WITH TIME ZONE -vs-
  • TIMESTAMP WITHOUT TIME ZONE

tersedia di pos SO ini . Yang ingin saya ketahui adalah: apakah ada kasus penggunaan yang valid untuk benar-benar menggunakan TIMESTAMP WITHOUT TIME ZONEatau harus dianggap sebagai anti-pola.

Marcus Junius Brutus
sumber
Pertanyaan ini berisiko ditutup "berdasarkan opini". Saya sudah mencoba memberikan beberapa pandangan objektif dalam jawaban saya di bawah ini.
Colin 't Hart
2
Masalah ini cukup nyata, setiap tipe data memiliki arti yang sangat berbeda. Jadi saya pasti tidak akan menganggap Pertanyaan ini sebagai dasar opini.
Basil Bourque

Jawaban:

30

Hal ini dinyatakan dalam banyak tempat, tapi saya pikir itu layak disebut selalu ketika kita membandingkan timestamp with time zonedengan timestamp without time zonejenis: yang timestamp WITH time zonetidak menyimpan zona waktu informasi bersama dengan stempel waktu . Apa yang dilakukannya adalah menyimpan setiap data dalam zona waktu UTC, sebagaimana dinyatakan dalam dokumen :

Untuk cap waktu dengan zona waktu, nilai yang disimpan secara internal selalu dalam UTC (Waktu Koordinasi Universal, secara tradisional dikenal sebagai Waktu Greenwich, GMT). Nilai input yang memiliki zona waktu eksplisit ditentukan dikonversi ke UTC menggunakan offset yang sesuai untuk zona waktu itu. Jika tidak ada zona waktu yang dinyatakan dalam string input, maka diasumsikan berada di zona waktu yang ditunjukkan oleh parameter TimeZone sistem, dan dikonversi ke UTC menggunakan offset untuk zona zona waktu.

Itu dianggap valid untuk digunakan timestamp WITHOUT time zonedalam situasi di mana (1) semuanya berada di zona waktu yang sama atau (2) lapisan aplikasi menangani zona waktu dan hanya menyimpan segala sesuatu di zona waktu tertentu (biasanya UTC). Tetapi itu juga dianggap sebagai anti-pola, sederhana karena solusi yang tepat untuk (1) adalah mengkonfigurasi pengaturan TimeZone ke zona waktu yang diberikan untuk sistem dan (2) sudah dipecahkan, karena PostgreSQL sudah menyimpan semuanya di zona waktu yang sama (UTC).

Sekarang, dengan kedua down, saya bisa datang hanya dengan satu alasan untuk digunakan timestamp WITHOUT time zone. Saat itulah Anda ingin menyimpan acara di masa depan dan semacam peringatan harus dipicu ketika kita sampai pada waktu itu. Itu bisa baik untuk timestamp WITH time zonejika, dan hanya jika, aturan yang ditetapkan oleh undang-undang kawasan tentang zona waktu tidak pernah berubah. Aturan paling umum yang berubah adalah tentang adopsi atau tidak, Day Light saving Time (DST).

Misalnya, bayangkan Anda berada di, katakanlah, 2013-06-15(belum dalam DST) jadwalkan beberapa acara terjadi 2013-01-15 10:00(yang sudah ada di DST), dan di 2013-06-15wilayah Anda telah ditunjuk untuk mengadopsi DST; tetapi, beberapa saat setelah itu, pemerintah mengubah aturan dan mengatakan wilayah Anda tidak akan lagi menggunakan DST, dan tiba-tiba waktu terjadwal Anda menjadi 2013-01-15 11:00(alih-alih 10:00), bahwa jika Anda menggunakan timestamp WITH time zone, dan menjaga agar konfigurasi TZ Anda tetap terbarui. Tentu saja Anda juga dapat memperhatikan bahwa ada kemungkinan untuk menangani kasus-kasus seperti itu juga dengan zona waktu, jika Anda melacak perubahan aturan di wilayah / zona waktu yang Anda minati, dan memperbarui catatan yang terpengaruh.

Patut disebutkan bahwa beberapa kawasan sering mengubah aturan ini (seperti di Brasil, beberapa negara bagian - bukan seluruh negara - sering berubah), tetapi dalam kebanyakan kasus itu mengubahnya lebih awal, sehingga pengguna Anda akan terpengaruh hanya oleh acara yang dijadwalkan sangat jauh dari waktu saat ini.

Dengan semua itu, saya hanya punya satu saran lagi. Jika Anda memiliki pengguna, log, atau apa pun di zona waktu yang berbeda, simpan zona waktu tempat mereka berasal dari suatu tempat dan pilih dan gunakan timestamp with time zone. Dengan cara itu Anda dapat (1) lintas peristiwa yang terjadi lebih dekat satu sama lain untuk sumber yang berbeda (terlepas dari zona waktu mereka) dan (2) menunjukkan waktu asli (waktu jam) peristiwa tersebut terjadi.

MatheusOl
sumber
Anda mengatakan: "Saya bisa datang hanya dengan satu alasan untuk menggunakan stempel waktu dengan zona waktu". Jika itu bukan kesalahan ketik, apakah Anda memang menyarankan bahwa "timestamp tanpa zona waktu" sebenarnya lebih tepat / kurang rentan untuk menghasilkan kesalahpahaman daripada "timestamp dengan zona waktu"? Bagi saya itu nampaknya kontra-intuitif.
Marcus Junius Brutus
@MarcusJuniusBrutus, maaf soal itu, itu memang salah ketik dan saya berpikir sebaliknya ... Periksa jawaban yang diedit.
MatheusOl
codeblog.jonskeet.uk/2019/03/27/… membahas secara mendalam skenario masa depan-acara-aturan-kekuatan-perubahan ini (dengan kesimpulan yang sama)
Beni Cherniavsky-Paskin
19

Iya nih. Ada kasus penggunaan untuk TIMESTAMP WITHOUT TIME ZONE.

  • Dalam aplikasi bisnis umum jenis ini hanya akan digunakan untuk:
    • Pemesanan janji masa depan
    • Mewakili waktu yang sama di berbagai zona waktu, seperti siang hari pada tanggal 23 di Tokyo dan di Paris (dua momen berbeda jam terpisah, waktu yang sama)
  • Untuk melacak momen, titik-titik spesifik pada timeline, selalu gunakan TIMESTAMP WITH TIME ZONE, bukan WITHOUT.

TIMESTAMP WITHOUT TIME ZONEnilai bukan titik pada timeline, bukan momen aktual. Mereka mewakili ide kasar tentang momen potensial , kemungkinan poin pada timeline sepanjang kisaran sekitar 26-27 jam (rentang zona waktu di seluruh dunia). Mereka tidak memiliki arti yang nyata sampai Anda menerapkan zona waktu atau mengimbangi dari UTC .

Mis: Natal

Misalnya, Anda perlu mencatat awal liburan / hari suci.

Table: holiday_

Column: year_         Type: SMALLINT
Column: description_  Type: VARCHAR
Column: start_        Type: TIMESTAMP WITHOUT TIME ZONE

Untuk mencatat fakta bahwa Natal dimulai setelah tengah malam pada 25 Desember tahun ini, kita perlu mengatakan 2016-12-25 00:00:00tanpa zona waktu. Di awal hari Santa, dia mengunjungi Auckland NZ tepat setelah tengah malam, karena itu adalah salah satu malam paling awal di dunia. Kemudian dia bekerja ke arah barat, saat tengah malam berikutnya, segera mencapai Filipina. Kemudian rusa itu bergerak ke arah barat, mencapai India pada tengah malam yang terjadi beberapa jam setelah tengah malam Auckland itu. Jauh kemudian masih tengah malam di Paris FR, dan masih kemudian tengah malam di Montreal CA. Semua kunjungan Santa ini terjadi pada saat-saat yang berbeda adalah waktu , namun semua terjadi tak lama setelah tengah malam, per tengah malam masing-masing daerah.

Jadi merekam 2016-12-25 00:00:00tanpa zona waktu sebagai awal Natal adalah informatif dan sah, tetapi hanya samar-samar. Sampai Anda mengatakan "Natal di Auckland" atau "Natal di Montréal", kami tidak memiliki momen khusus dalam waktu. Jika Anda merekam momen aktual setiap kali giring mendarat, Anda akan menggunakan TIMESTAMP WITH TIME ZONEdaripada WITHOUTtipe.

Mirip dengan Natal adalah Malam Tahun Baru. Ketika Times Square Ball jatuh di New York , orang-orang di Seattle masih mendinginkan sampanye mereka dan menyiapkan tanduk pesta mereka . Namun kami akan merekam ide momen Tahun Baru seperti 2017-01-01 00:00:00pada a TIMESTAMP WITHOUT TIME ZONE. Sebaliknya, jika kita ingin merekam ketika bola jatuh di New York, atau ketika orang-orang di Seattle meniup terompet mereka, kita lebih suka menggunakan TIMESTAMP WITH TIME ZONE(tidak WITHOUT) untuk merekam momen aktual itu, masing-masing berjarak tiga jam dari yang lain.

Mis: Pergeseran Pabrik

Contoh lain mungkin merekam kebijakan yang melibatkan waktu jam dinding di berbagai lokasi. Katakanlah kita memiliki pabrik di Detroit, Düsseldorf, dan Delhi. Jika kita mengatakan bahwa di ketiga pabrik, shift pertama dimulai pada jam 6 pagi dengan istirahat makan siang pada jam 11:30, yang dapat dicatat sebagai a TIMESTAMP WITHOUT TIME ZONE. Sekali lagi, informasi ini berguna secara samar-samar tetapi tidak menunjukkan saat tertentu dalam waktu sampai kita menerapkan zona waktu. Hari baru baru sadar di timur. Jadi pabrik Delhi akan menjadi yang pertama dibuka pada pukul 6 pagi. Beberapa jam kemudian, pabrik Düsseldorf mulai bekerja pukul 6 pagi. Tetapi pabrik Detroit tidak akan benar-benar terbuka sampai enam jam kemudian, ketika 6:00 terjadi.

Bandingkan ide ini (tentang kapan shift pabrik umumnya dimulai) dengan fakta historis kapan setiap pekerja pabrik jam-in untuk memulai shift mereka pada hari tertentu. Clock-in adalah momen nyata, titik aktual di timeline. Jadi kami akan mencatatnya dalam kolom tipe TIMESTAMP WITH TIME ZONEbukan WITHOUTtipe.

Jadi, ya, ada kasus penggunaan yang sah untuk TIMESTAMP WITHOUT TIME ZONE. Tetapi dalam pengalaman saya dengan aplikasi bisnis, mereka relatif jarang. Dalam bisnis, kita cenderung peduli pada saat-saat aktual: kapan faktur benar-benar tiba, kapan tepatnya kontrak itu berlaku, pada saat apa transaksi bank itu dilaksanakan. Jadi dalam situasi umum seperti itu, kami menginginkan TIMESTAMP WITH TIME ZONEtipenya.

Untuk diskusi lebih lanjut, lihat Jawaban saya untuk Pertanyaan serupa, Haruskah saya menyimpan stempel waktu UTC atau waktu lokal untuk shift

Postgres

Perhatikan bahwa Postgres khusus tidak pernah menyimpan informasi zona waktu yang ditentukan saat memasukkan stempel waktu.

  • TIMESTAMP WITH TIME ZONE
    • Setiap zona waktu atau offset tertentu yang disertakan dengan data input digunakan untuk menyesuaikan nilai ke UTC dan disimpan. Info zona / offset yang lewat kemudian dibuang. Pikirkan TIMESTAMP WITH TIME ZONEsebagai TIMESTAMP WITH RESPECT FOR TIME ZONE.
    • Input pukul 12 siang pada tanggal 7 Maret tahun ini di India akan disesuaikan waktunya dengan UTC dengan mengurangi lima setengah jam: 6:30 pagi.
  • TIMESTAMP WITHOUT TIME ZONE
    • Setiap zona waktu atau offset tertentu yang disertakan dengan data input sepenuhnya diabaikan.
    • Masukan dari pukul 12:00 siang pada tanggal 7 Maret tahun ini di India dicatat sebagai pukul 12:00 pada tanggal 7 Maret tahun ini tanpa penyesuaian.

Standar SQL hampir tidak menyentuh pada masalah tipe dan perilaku data tanggal-waktu. Sehingga database bervariasi secara luas dalam penanganan tanggal-waktu.

Basil Bourque
sumber
lebih jauh dengan shift pabrik (atau rumah sakit), siapa pun yang bekerja di pemakaman pada hari-hari pergantian DST akan mencatat jam mereka secara salah dari itu dicatat tanpa zona waktu ..
Jasen
Saya pikir ada kesalahan ketik dalam contoh terakhir: 'Sebuah masukan 12.00 siang pada tanggal 7 Maret .. harus 'tercatat sebagai 12 : 00'(tidak 21:00)
TmTron
11

Saya ingin menambahkan pandangan lain untuk ini, yang bertentangan dengan banyak dari apa yang telah ditulis dalam jawaban lain. Menurut pendapat saya timestamp with time zonememiliki sangat sedikit kasus penggunaan yang valid, dan timestamp without time zonesecara umum lebih disukai.

Pertama, Anda harus memahami pola "UTC di mana-mana", yang umumnya direkomendasikan untuk semua aplikasi yang tidak memiliki persyaratan khusus. Ini berarti bahwa aplikasi Anda harus mewakili semua cap waktu di UTC, di mana saja, sepanjang waktu. Tentu saja, Anda akan menunjukkan tanggal / waktu setempat kepada pengguna, tetapi idenya adalah untuk mengonversikannya di tepi program Anda, saat menampilkan tampilan. Ini adalah tempat yang tepat untuk menggabungkan timestamp UTC (yang mungkin Anda muat dari database) dan zona waktu pengguna (yang mungkin berasal dari browser) ke cap waktu lokal.

Jika Anda mengikuti pola ini, maka timestamp with time zonemerupakan pola anti. Semua jenis ini dilakukan adalah membuat PostgreSQL melakukan konversi zona waktu saat membaca dan menulis stempel waktu, berdasarkan TimeZonevariabel sesi PostgreSQL Anda . Alih-alih berurusan dengan zona waktu di bagian paling tepi dari aplikasi Anda, Anda telah memperkenalkannya ke dalam inti, ke dalam komunikasi dengan database Anda. Anda harus berhati-hati untuk selalu TimeZonemengonfigurasi PostgreSQL dengan benar setiap saat, menambahkan titik kegagalan dan kebingungan yang tidak perlu.

Dan untuk apa? Jika Anda mengikuti pola UTC di mana-mana, aplikasi Anda hanya memiliki stempel waktu UTC; jadi mengapa meminta database Anda untuk melakukan konversi zona waktu? Anda bisa menyimpannya dalam timestamp without time zonekolom, dan memperlakukannya seperti itu selalu UTC. Tidak ada konversi, tidak ada zona waktu, tidak ada komplikasi.

Shay Rojansky
sumber
2
Saya pikir para pendukung timestamptz juga mendukung pola "UTC di mana-mana". Hanya saja peraturan hanya akan diberlakukan di tingkat basis data alih-alih hanya mengandalkan pengembang aplikasi / API untuk menegakkannya? Jika Anda dapat menerapkan praktik itu, mengapa tidak? Anda juga dapat menerapkan bahwa semua koneksi postgres mengatur zona waktu mereka ke UTC. Bahkan jika tidak, format ISO akan berisi tz offset. Jadi bukankah hal itu sama dengan UTC di mana pun selain ditegakkan?
iamnat
3
Pertama, jika PostgreSQL TimeZone Anda disetel ke sesuatu selain UTC dan Anda menggunakan timestamptz, program Anda membaca cap waktu non-UTC. Ini bukan pola "UTC di mana-mana", dan tergantung pada bahasa klien Anda, mungkin atau mungkin tidak membuat banyak komplikasi. Entah Anda UTC di mana-mana, atau Anda menggunakan stempel waktu lokal ....
Shay Rojansky
Kedua, sekali lagi, jika Anda UTC di mana-mana dalam aplikasi Anda, sama sekali tidak ada offset untuk mengirim dalam format ISO untuk cap waktu Anda. Spesifikasinya akan bervariasi antar bahasa, tetapi idealnya Anda harus menggunakan tipe klien yang tidak mampu mewakili apa pun kecuali cap waktu UTC (misalnya a Instancedi NodaTime / JodaTime). Anda pada dasarnya menggambarkan situasi di mana "UTC di mana-mana" hampir diikuti, atau agak diikuti ...
Shay Rojansky
Sekali lagi, sangat mudah untuk membayangkan contoh PostgreSQL baru sedang diatur pada beberapa server, tanpa sengaja mempertahankan zona waktu mesin lokal yang dikonfigurasi secara default. Aplikasi membaca dari server ini dan mendapatkan cap waktu lokal di zona waktu yang sama sekali sewenang-wenang (tempat server berada). Mengapa kita menginginkan komplikasi tambahan ini?
Shay Rojansky
1
Itu bisa, tetapi kemudian akan lebih tidak masuk akal untuk digunakan timestamptz. Inti dari tipe ini adalah untuk melakukan konversi zona waktu sebagai nilai yang dibaca dan ditulis ke PostgreSQL (secara internal dalam database, stempel waktu selalu disimpan sebagai UTC). Selalu mengatur zona waktu sesi ke UTC secara efektif menonaktifkan konversi itu, jadi mengapa menggunakan timestamptzsama sekali? Dengan kata lain, jika nilai-nilai dalam database adalah UTC, dan nilai-nilai yang masuk dan keluar dari database selalu UTC, lalu mengapa memiliki kesadaran zona waktu sama sekali dalam database Anda?
Shay Rojansky
2

The datetimestamp juga tidak termasuk zona waktu, namun banyak orang menggunakannya.

Tentu saja, itu sendiri bukanlah jawaban.

Ini berlaku untuk menggunakan timestampdan dateuntuk cap waktu dan tanggal yang selalu dalam zona waktu yang sama, atau disimpan relatif terhadap beberapa zona waktu yang diketahui.

Jika zona waktu selalu sama atau implisit, maka lebih baik untuk memindahkannya daripada tidak menyimpannya (informasi yang berlebihan).

Stempel waktu juga dapat digunakan untuk menyimpan informasi teknis seperti yang digunakan dalam log aplikasi atau untuk pengukuran kinerja. Dalam hal ini, zona waktu juga tidak penting.


Sebaliknya, jika Anda merancang atau bekerja pada sistem terdistribusi atau di sistem mana pun di mana bagian-bagian sistem akan didistribusikan di berbagai zona waktu, itu mungkin dianggap sebagai anti-pola untuk tidak menggunakan timestamp with timezone , meskipun beberapa sistem mungkin dirancang untuk dijalankan dalam satu zona waktu, mis. UTC. Dalam hal ini logika zona waktu mungkin didorong ke dalam lapisan aplikasi - tapi saya akan menganggap ini sebagai anti-pola, ya.

Colin 't Hart
sumber
Saya mengerti bahwa dalam kasus-kasus tertentu tidak ada salahnya untuk digunakan timestamp without timezone, tetapi apakah pernah membeli saya apa pun? Kalau tidak, mengapa saya harus repot-repot jika timestamp with timezone datajenisnya selalu sama atau lebih sesuai?
Marcus Junius Brutus
Tidak menyimpan informasi yang berlebihan akan menjadi argumen utama saya. Saya kira aritmatika tanggal pada timestamp without timezoneakan lebih cepat juga, tetapi itu mungkin hanya penting jika Anda memproses miliaran baris ...
Colin 't Hart
1
@ Colin'tHart timestampdan timestamptzkeduanya disimpan dengan cara yang sama. Tidak ada informasi zona waktu yang disimpan dalam a timestamptz, tetapi sebaliknya dikonversi ke UTC untuk penyimpanan. Menurut saya, selalu gunakan timestamptzketika cap waktu yang dimaksud menunjukkan waktu absolut . Itu semua timestamptzartinya. Saya sudah menulis tentang ini di sini .
fphilipe
2

Tampaknya menggoda untuk menyimpan dan memproses tanggal / waktu dalam waktu lokal jika aplikasi Anda terbatas pada zona waktu tunggal tetapi saya yakin ini adalah kesalahan.

Ketika beralih dari waktu penghematan siang hari ke waktu standar satu jam di waktu lokal diulangi (dengan asumsi perbedaannya adalah satu jam). Tempat saya tinggal ini biasanya terjadi sekitar jam 2 pagi sehingga waktu setempat berjalan 01:58, 01:59, 01:00 dan hanya naik menjadi 02:00 pada akhir jam yang diulang.

Jika Anda mencoba untuk memesan acara berdasarkan waktu menggunakan waktu setempat, itu berarti acara dari dua jam yang terpisah berbaur bersama dan tidak muncul dalam urutan di mana mereka benar-benar terjadi.

Sebagai perbandingan, UTC tidak memiliki masalah ini dan memesannya dengan bersih. Jadi, bahkan ketika bekerja dengan hanya satu zona waktu, Anda ingin DB menyimpan dan memproses waktu dalam UTC dan mengonversikan ke / dari waktu lokal untuk input / tampilan. Ini adalah perilaku TIMESTAMP DENGAN ZONA WAKTU.

Steve Fosdick
sumber