Mengapa tidak ada tipe data "Hanya-Tanggal" yang sebenarnya?

24

Saya sangat frustrasi karena harus menggunakan nilai DateTime untuk set data yang benar-benar "hanya sehari." Ulang tahun menjadi contoh paling umum, tetapi ini muncul dalam aplikasi bisnis setiap saat.

Saya telah terbiasa mengatur bagian Waktu dari "hanya tanggal" catatan ke "siang" (yang menghindari tanggal yang selalu berubah tidak peduli zona waktu). Ini seperti hack, dan saya selamanya menemukan bug dari junior devs yang tersandung masalah ini.

Waktu selalu relatif terhadap titik tertentu. 4PM adalah 4 jam pasca meridian, atau siang hari. Titik tertinggi matahari dalam transit dapat diamati, dan memungkinkan kita untuk mengatur sistem koordinat. 3 jam sebelum tengah hari (Ante Meridian), 2 jam setelah tengah hari, 1441899402938 milidetik sejak 1 Januari 1970. Bagi orang yang dibesarkan di dunia Cartesian, ini adalah sifat kedua.

Tapi Kalender kami ada sebelum Descartes. Argumen saya adalah bahwa itu lebih tepat dianggap sebagai enumerasi di mana fungsi modulo diterapkan. Senin mengikuti Minggu, dan seterusnya sampai Anda sampai pada kenyataan bahwa Minggu mengikuti Sabtu. Tidak ada positif dan negatif, itu adalah nilai modulus, atau absolut.

Demikian pula dengan pengulangan bertahun-tahun. Setiap 365 hari (atau lebih) ada beberapa hari khusus untuk saya: ulang tahun, ulang tahun, ulang tahun anak-anak, dll. Aplikasi penjadwalan bisnis penuh dengan contoh pertemuan setiap tujuh hari, Selasa pertama setiap bulan, dll. Hanya karena kita BISA memetakan ini ke angka floating point, dan sebenarnya memetakannya ke angka tersebut memecahkan BANYAK masalah yang benar-benar sulit dengan cara lama, tetapi itu tidak berarti itu satu-satunya cara untuk melakukannya.

Kesadaran dan pemahaman tentang sifat "pasak persegi dalam lubang bundar" menggunakan DateTimes untuk menyimpan Tanggal membuat Anda seorang programmer yang lebih baik menurut saya.

Apakah ada nilai dalam aplikasi yang secara eksplisit dimaksudkan sebagai aplikasi penjadwalan dalam mendefinisikan kelas Date, atau "set sepanjang waktu ke siang hari" pendekatan terbaik? Masalah apa yang mungkin ada dengan menggunakan DateTime dan mengatur komponen Waktu ke Tengah Hari? Dapatkah pergeseran zona waktu diperhitungkan dalam pendekatan semacam itu? Saya telah menggunakan MomentJS, tapi saya pikir itu hanya kelas Date yang lebih baik.

Michael Blackburn
sumber
7
ini pertanyaan yang cukup menarik. Ambil contoh ulang tahun, itu benar-benar masuk akal pada manusia, saya hidup di satu tempat dan semua orang bangun pada saat yang sama, semacam cara. segera setelah Anda perlu mengekspresikannya secara matematis, itu menjadi sangat kompleks. Sama dengan hal-hal seperti shift kerja mulai / berakhirnya waktu dll mereka tidak 'kali' mereka adalah 'jam sehari di zona waktu di mana Anda bekerja'
Ewan
3
NodaTime (pustaka C # untuk Tanggal & Waktu) memiliki tipe tanggal.
CodesInChaos
5
Simpan waktu Anda sebagai UTC, tidak ada masalah tanggal, tidak ada masalah zona waktu.
Loren Pechtel
3
"Tapi Tuhan ini sepertinya hack, dan aku selamanya menemukan bug dari para junior devs yang tersandung masalah ini." - mengapa Anda tidak membuat kelas DateOnly Anda sendiri atau apa pun dan menyebutnya sehari.
Brandin
5
@MichaelBlackburn aku serius. Penjelasan Anda terdengar persis situasi untuk tipe data sendiri yang memberlakukan aturan bisnis (hanya tanggal, misalnya Anda dapat menyimpannya sebagai "DateTime" secara internal dengan bagian waktu yang diatur ke siang hari), tetapi kemudian hanya mengekspos bagian yang Anda inginkan (bulan , hari, dll. tahun / tanpa tahun).
Brandin

Jawaban:

15

Pertama-tama, mari kita menyingkir: ulang tahun adalah satu hal, tanggal lahir adalah hal lain. Sebuah Ulang Tahun adalah tipe data yang eksotis karena kekurangan tidak hanya komponen jam, menit dll tetapi juga tidak memiliki komponen tahun. Jika Anda benar-benar ingin berurusan dengan ulang tahun, saya akan merekomendasikan menemukan tipe data Anda sendiri yang tidak mengandung apa-apa selain nomor bulan dan nomor hari, dan tidak terkait dengan salah satu tipe data tanggal-waktu bawaan.

Di sisi lain, jika Anda ingin juga melacak tahun kelahiran, maka yang Anda miliki bukan hari ulang tahun, itu adalah tanggal kelahiran . Jadi, pertanyaannya sekarang menjadi mengapa tidak ada tipe data hanya tanggal, sehingga Anda dapat dengan mudah mewakili tanggal lahir, dan sebaliknya bahasa populer tampaknya memaksa Anda untuk menggunakan beberapa jenis yang juga mencakup komponen waktu.

Izinkan saya secara singkat menyebutkan bahwa tidak benar bahwa semua bahasa pemrograman hanya menawarkan tipe data temporal yang mencakup komponen waktu. Saya telah menemukan tipe data hanya tanggal di RDBMSes dan dalam dialek SQL yang sesuai. Tetapi itu tidak relevan: fakta bahwa tipe-tipe data ini ada tidak berarti bahwa mereka adalah hal yang baik untuk dimiliki, dan RDBMSes memiliki sejarah panjang penyimpanan yang membingungkan dengan representasi.

Anda akan memahami mengapa memiliki tipe data hanya tanggal seperti itu adalah saat Anda menyadari bahwa waktu adalah koordinat. Kebanyakan orang memiliki gagasan yang sangat kabur tentang apa waktu itu, dan gagasan ini mengandung gagasan budaya yang misterius seperti tahun, bulan, dan hari, tanpa menyadari bahwa gagasan ini hanya representasional : mereka hanya berguna untuk merepresentasikan waktu kepada manusia, dan untuk menerima waktu sebagai input dari manusia. Pada setiap lapisan di bawah kontrol GUI entri-waktu yang sebenarnya, waktu harus, dan biasanya, direpresentasikan sebagai koordinat waktu, yang merupakan sejumlah satuan waktu sejak beberapa asal.

Misalnya, dalam DateTimetipe data Microsoft Dotnet, satuan waktu adalah 100 nanodetik, dan asal waktu adalah 12:00 tengah malam, 1 Januari 0001 M

Contoh lain dari notasi representasional misterius, adalah pengukuran sudut menggunakan derajat, menit derajat, dan detik derajat. Tentu saja, untuk menyelesaikan perhitungan yang bermanfaat, Anda harus menggunakan radian secara internal, dan jika perlu, konversi ke dan dari derajat saat berinteraksi dengan pengguna manusia.

Jadi, jangan bingung representasi pengukuran yang dapat dibaca manusia dengan sifat sebenarnya dari pengukuran tersebut. Cukup sering metode ideal untuk merealisasikan pengukuran, yang paling sesuai dengan sifat pengukuran, sangat berbeda dari representasi pengukuran yang dapat dibaca manusia.

Mengingat semua ini, permintaan Anda untuk tipe data temporal yang hanya mewakili tanggal sama dengan permintaan untuk tipe data sudut yang hanya akan mampu mewakili derajat, secara eksplisit mencegah presisi yang lebih besar. Jenis data seperti itu akan sangat terbatas, dan pada akhirnya tidak berguna, karena Anda harus mengubahnya ke dan dari radian untuk mendapatkan sesuatu yang berguna dilakukan dengan itu.

Masalah Anda dengan tanggal lahir adalah bahwa Anda memiliki koordinat waktu yang tidak tepat : orang itu, tentu saja, dilahirkan pada saat tertentu dalam waktu, tetapi jam dan menit tidak dicatat oleh rumah sakit, atau kami tidak peduli dengan mereka. Jadi, apa yang sebenarnya terjadi adalah bahwa koordinat waktu tanggal dan waktu kelahiran Anda memiliki margin kesalahan, toleransi atau ketidakpastian jika Anda inginkan, dan yang terbaik untuk memperlakukannya adalah seperti itu: letakkan tepat di tengah hari ini, dan pertimbangkan ketidakpastian 12 jam hingga 12 jam. Dan itulah solusi yang secara intuitif Anda dapatkan.

Mike Nakis
sumber
4
Ini tidak benar untuk "Days" yang merupakan konsep yang bahkan lebih tua dari Time. Mereka paling tepat dianggap sebagai enumerasi, atau modulus. Hari Minggu mengikuti hari Senin, dll sampai kita kembali ke hari Minggu, yang mengikuti hari Sabtu. Benar-benar hal yang berbeda.
Michael Blackburn
10
Nah tentu saja rumah sakit menuliskan waktu kelahiran - yang praktek standar di kebanyakan rumah sakit. Itu bukan masalah sama sekali. Masalahnya adalah bahwa untuk keperluan memperingati acara (ulang tahun, liburan, hari jadi, dll) orang tidak menggunakan atau menginginkan resolusi yang lebih baik dari 1 hari. Pergi tanyakan orang pertama yang Anda lihat ketika ulang tahun mereka, dan mereka akan memberi Anda sebulan dan sehari, tetapi tidak pernah satu jam dan menit. Juga: kami menggunakan unit yang mencakup skala sepanjang waktu: milimeter, kilogram, megawatt, dan memang, mikrofarad.
Caleb
4
-1: Tidak semua penggunaan waktu mewakili satu momen waktu. Ulang tahun adalah ide yang berbeda, diwakili oleh satu bulan dan satu hari di kalender Gregorian. Masuk akal untuk bertanya, "Apakah ini hari ulang tahun Kevin?" Jawabannya tergantung pada lokasi. Jika saya berada di Sydney, ini bisa menjadi hari ulang tahun saya, tetapi jika saya berada di Honolulu, itu belum akan berlangsung selama beberapa jam.
kevin cline
6
@ MikeNakis Hasilnya adalah microamps, bukan omong kosong. Lebih penting: ketika Anda menggunakan tanggal daripada satu detik atau milidetik, Anda biasanya berbicara tentang sepanjang hari - periode waktu - daripada waktu tertentu, dan tergantung pada konteksnya itu mungkin merupakan peristiwa yang berulang.
Caleb
4
OP berbicara tentang ulang tahun, yang diwakili dengan tepat oleh java.util.MonthDay. Ulang tahun bukanlah ukuran, itu adalah konsep manusia tentang hari yang berulang setiap tahun. Ada banyak ide manusia tentang waktu yang tidak diwakili oleh satu titik waktu.
kevin cline
9

Tanggal dan waktu adalah banyak hal berbeda tergantung pada konteksnya, dan Anda memerlukan banyak jenis yang berbeda untuk mencakup semua kasus penggunaan.

The DateTimejenis hadir dalam banyak bahasa merupakan titik yang tepat dalam waktu ( "waktu sesaat"). Di luar ini, kami memiliki sejumlah konsep waktu dan rentang waktu relatif atau "manusia" seperti hari kalender, tanggal berulang, bulan, tahun, dll. Dalam banyak kasus ambigu dan tergantung konteks. Jenis-jenis ini tidak berguna secara universal, tetapi diperlukan dalam domain aplikasi spesifik seperti kalender, alat penjadwalan, dan aplikasi lain yang berinteraksi dengan konsep waktu manusia.

Jika Anda menulis sesuatu seperti aplikasi kalender, Anda pasti akan mendapat manfaat dari menggunakan perpustakaan seperti Joda-time yang menyediakan serangkaian jenis waktu yang lebih kaya. Misalnya LocalDate, kencan tanpa waktu. Ini memiliki semantik yang berbeda dari yang biasa DateTimedengan bagian waktu diatur ke nol, karena DateTimemasih menunjukkan titik waktu tertentu (tengah malam di zona waktu tertentu), sementara LocalDatemenunjukkan sepanjang hari, dan tidak terikat pada zona waktu tertentu. Ini juga berarti Anda tidak dapat langsung menerjemahkan yang satu ke yang lain.

LocalDatetentu saja lebih sederhana daripada DateTimekarena tidak harus mempertimbangkan zona waktu, tetapi Anda harus mengetahui masalah-masalah lain, misalnya bahwa tanggal saat ini mungkin sebenarnya mundur ketika Anda melintasi zona waktu, dan bahwa instan dalam waktu yang sama mungkin sesuai dengan tanggal yang berbeda di zona waktu yang berbeda. Jika Anda menggunakan tanggal lokal di aplikasi jaringan atau web, Anda harus sangat berhati-hati tentang masalah ini. Menghapus bagian waktu dari tanggal tidak memecahkan masalah mendasar zona waktu! Dan jika Anda mempertimbangkan tanggal bersejarah dan budaya yang berbeda, itu menjadi lebih sulit, karena tanggal yang sama mungkin sesuai dengan kejadian yang sangat berbeda dalam waktu dalam mengatakan kalender Julian versus kalender Gregorian.

Sekarang Anda bertanya mengapa bahasa tidak memiliki sesuatu seperti LocalDate built-in . Pertama, beberapa bahasa seperti SQL dan Visual Basic memiliki tipe tanggal tanpa waktu. Dan Java juga telah menambahkan LocalDatedalam versi terbaru. Tetapi platform lain seperti .Net tidak. Hanya perancang bahasa yang benar-benar dapat menjawab mengapa ini tidak termasuk dalam perpustakaan standar, tetapi dugaan saya adalah bahwa "waktu sesaat" secara konseptual sederhana dan bermanfaat secara universal, sedangkan konsep waktu lainnya hanya berguna untuk domain aplikasi tertentu (seperti kalender, dll. .). Jadi masuk akal untuk membiarkan pengembang aplikasi menulis jenis kustom untuk menangani kasus penggunaan yang lebih kompleks, atau membiarkannya ditangani oleh perpustakaan pihak ketiga (seperti waktu Joda).

JacquesB
sumber
5

Saya sangat frustrasi karena harus menggunakan nilai DateTime untuk set data yang benar-benar "hanya sehari." Ulang tahun menjadi contoh paling umum, tetapi ini muncul dalam aplikasi bisnis setiap saat.

Ini mungkin karena kalender itu rumit dan digunakan dalam banyak cara yang berbeda sehingga tidak ada yang bisa menentukan kelas yang sederhana namun cukup umum untuk berguna di banyak bidang.

Jenis tanggal yang biasa ditemukan dalam bahasa pemrograman dapat digunakan untuk secara akurat menentukan tanggal transaksi dalam sistem komputer. Kasing lain mungkin membutuhkan perpustakaan khusus.

Berikut adalah daftar pendek fakta tentang kalender, yang menunjukkan kompleksitasnya - kebanyakan dari mereka bersifat historis, jadi jika Anda membatasi perhatian Anda pada tanggal setelah 1.1.1970, Anda tidak akan terpengaruh oleh ini. Namun jika aplikasi Anda perlu bekerja dengan tanggal yang terjadi sebelum akhir abad ke-19, maka fakta-fakta ini akan berpengaruh. Kasing yang mungkin digunakan adalah basis data historis segala jenis (buku, silsilah) tetapi juga aset perusahaan atau organisasi besar yang masih beroperasi hingga saat ini.

Semua fakta ini dikutip dari FAQ yang sangat baik yang ditemukan di perpustakaan kalender untuk OCaml yang ditulis oleh Julien Signolles.

  1. Kalender Julian diperkenalkan oleh Julius Caesar pada 45 SM. Itu biasa digunakan sampai tahun 1500-an, ketika negara-negara mulai berubah ke kalender Gregorian (bagian 2.2). Namun, beberapa negara (misalnya, Yunani dan Rusia) menggunakannya ke tahun 1900-an, dan gereja Ortodoks di Rusia masih menggunakannya, seperti halnya beberapa gereja Ortodoks lainnya.

  2. Berganti dari Julian ke kalender Gregorian tidak terjadi secara seragam, dan tergantung dari tahun perubahan, 10 hingga 13 hari telah dihapus. Misalnya di Perancis 9 Des 1582 diikuti oleh 20 Des 1582 dan di Yunani 9 Mar 1924 diikuti oleh 23 Mar 1924.

  3. Bahkan di era modern, banyak kalender yang berbeda digunakan (Gregorian, Orthodox, Islam dan Cina) untuk mengutip beberapa, yang semuanya menggunakan cara yang berbeda untuk menghitung tahun dan peringatan atau tanggal perayaan keagamaan.

Sekarang Anda berharap untuk jenis tanggal yang dibundel dengan operasi yang berguna untuk operasi bisnis umum. Saya kira tidak ada yang namanya operasi bisnis umum. Misalnya, di dunia keuangan, kita perlu menghitung:

  1. Fraksi tahun (seperti "6 bulan" sesuai dengan "0,5"), yang digunakan bersama dengan suku bunga untuk menghitung bunga aktual pada pinjaman untuk jangka waktu tertentu. Ada 6 sampai 10 resep untuk menghitung pecahan ini, masing-masing berbeda dalam cara mereka menangani panjang tahun kabisat, posisi periode sehubungan dengan hari terakhir bulan Februari dan durasi satu bulan.

  2. Pengguliran tanggal, saat menghitung hari jadi, kami menggunakan kalender bisnis dan aturan (dipilih dari lebih dari 6 aturan yang berbeda) untuk mengubah hari jadi dari hari libur ke hari kerja.

Bagi orang yang bekerja di industri keuangan, semua jenis kalender yang tidak menerapkan semua fungsi dan aturan ini tidak berguna. Sangat mungkin bahwa banyak industri lain memiliki jenis kebiasaan dan konvensi lain yang memerlukan perhitungan khusus pada kalender.

Apakah ada nilai dalam aplikasi yang secara eksplisit dimaksudkan sebagai aplikasi penjadwalan dalam mendefinisikan kelas Date, atau "set sepanjang waktu ke siang hari" pendekatan terbaik? Masalah apa yang mungkin ada dengan menggunakan DateTime dan mengatur komponen Waktu ke Tengah Hari? Dapatkah pergeseran zona waktu diperhitungkan dalam pendekatan semacam itu? Saya telah menggunakan MomentJS, tapi saya pikir itu hanya kelas Date yang lebih baik.

Jika Anda perlu melacak satu hari kalender, cara terbaik mungkin menggunakan bilangan bulat besar yang mewakili hari Julian pada hari kalender itu. Algoritma untuk mengkonversi bolak-balik dari hari Julian ke hari kalender - dijelaskan dengan tahun, bulan dan kalender - diketahui secara luas dan diuji secara menyeluruh, sehingga Anda dapat dengan mudah mengimplementasikannya dalam aplikasi Anda - dan mencari tahu aturan apa pun yang berkaitan dengan Anda kasus untuk menghitung hari jadi dari suatu peristiwa yang terjadi pada tanggal 29 Februari.

Michael Le Barbier Grünewald
sumber
2

Saya pikir Mike Nakis dalam jawabannya di atas melakukan pekerjaan yang lebih baik daripada yang saya dapat menjelaskan bagaimana waktu secara umum adalah koordinat terukur absolut dan komunikasi lainnya, keadaan yang dinyatakan atau kegigihan koordinat waktu itu hanyalah representasi abstrak dari koordinat waktu tersebut.

Anda berbicara dengan representasi seperti itu ketika merujuk ke Day of the Week hanya sebagai semacam representasi modulus dari titik waktu aktual. Pada kenyataannya itu agak lebih rumit dari itu. Jika Anda ditugaskan untuk menulis fungsi yang akan mengembalikan Day of the Week untuk titik waktu tertentu, pertimbangkan informasi berikut yang akan Anda perlukan sebagai input untuk algoritma tersebut. Anda akan memerlukan titik waktu, Kalender, zona waktu untuk dipertimbangkan (Perlu diingat, zona waktu berubah SELURUH WAKTU sehingga Anda perlu tahu kapan zona waktu efektif itu mulai ketika berakhir pada koordinat waktu tertentu. Korea Utara baru-baru ini saja misalnya mengubah mereka!), dan jika waktu Musim Panas berlaku, ini juga berubah seiring waktu. Sekarang pertimbangkan jika Anda diberi DateTime di zona waktu lokal,

Anda dapat melihat betapa rumitnya pertanyaan yang tampaknya sederhana ini benar-benar dapat.

Saya tahu rasa sakit yang Anda rasakan ketika saya berada di posisi Anda pada satu titik memperbaiki semua bug dalam aplikasi penjadwalan kunjungan untuk produk yang ditulis oleh pengembang yang tidak berpengalaman. Semuanya harus dibuang.

Waktu memang sebuah koordinat, tetapi selain Tanggal semata, pertimbangkan data sensitif waktu lainnya yang mungkin diperlukan seperti:

Durasi: Rentang milidetik yang mungkin terjadi yang menandakan panjang atau perjalanan waktu tanpa koordinat waktu tertentu yang ditentukan. Kasus penggunaan mungkin,

Sebagai pengguna, saya ingin tugas ini dilakukan 15 detik setelah selesainya pekerjaan tengah malam setiap hari Rabu.

Interval: Rentang waktu antara dua koordinat waktu tertentu. Kasus penggunaan di mana Anda mungkin ingin mempertimbangkan suatu interval.

Sebagai pengguna, saya perlu melihat setiap Hari dalam Bulan sepenuhnya terkandung dalam interval waktu tertentu.

Poin cepat lain yang ingin saya sampaikan adalah bahwa Anda membuat komentar tentang nomor Floating Point untuk data berbasis waktu dan saya menyarankan untuk tidak melakukannya. Aritmatika titik mengambang tak terhindarkan mengarah pada kesalahan pembulatan yang mungkin tidak memberi Anda pengukuran setepat yang diperlukan untuk waktu.

Jadi kesimpulannya, semua informasi ini pasti mengarah pada pertimbangan desain berikut:

  • Poin atau rentang waktu tertentu harus dipertahankan dalam UTC atau beberapa tipe data yang berisi informasi yang cukup untuk dengan mudah diabstraksi kembali ke UTC jika diperlukan
  • Logika aplikasi harus ditulis ke format UTC atau rentang koordinat UTC menjadi status data representasional yang lebih mudah dicerna untuk pengguna akhir.
  • Durasi penting harus bertahan dalam milidetik
  • Preferensi spesifik pengguna lokal atau pengguna akhir pada tampilan data apa pun mengenai waktu harus dipertahankan sebagai data tambahan dan diperlakukan seperti opsi tampilan. (Misalnya. Kios A, Zona Waktu Pusat, format Waktu Militer, atau preferensi Pengguna B, Waktu Standar di Tel Aviv (GMT + 7: 00) zona waktu, dll ...)
  • Hindari nomor FP
maple_shaft
sumber
1
Semua ini "tak terhindarkan". Ini mungkin umum untuk banyak aplikasi, tetapi Large Hadron Collider berkaitan dengan peristiwa pada skala nanosecond. Waktu sistem telah pindah ke mikrodetik karena milidetik tidak memiliki cukup presisi. Aplikasi kalender harus memiliki konsep tanggal yang terjadi pada hari kalender lokal baik Anda berada di zona waktu yang sama dengan yang Anda buat acara.
Alan Shutko
1
@AlanShutko Dan ya bahwa "data tambahan" yang diperlukan adalah hal-hal seperti zona waktu lokal, dan Hari, dan data penting lainnya yang harus diambil. Ini semua hanya abstraksi namun ke satu titik waktu, bahkan jika titik waktu tidak penting untuk algoritma Anda. Sejauh skala nanosecond dan bahkan microsecond, jawaban saya diarahkan lebih ke arah perangkat lunak jenis web dan LOB. Saya ragu bahwa bahasa pilihan LHC adalah C # atau Javascript.
maple_shaft
1
Milidetik sangat bagus untuk proses fisik yang berulang. Untuk aktivitas manusia, kadang-kadang unit yang sesuai adalah nominal hari, mis. Jika dikirim pada akhir hari itu akan tersedia untuk digunakan di tujuan tiga hari kemudian.
kevin cline
Di masa lalu saya telah mempertimbangkan menggunakan angka floating point 64-bit untuk koordinat waktu, dan yang lebih penting untuk rentang waktu, karena mereka memungkinkan Anda untuk mengekspresikan jumlah kecil dengan presisi tinggi, serta jumlah besar, di mana kehilangan presisi tidak terlalu menjadi masalah. . (Jadi bagaimana jika Dinosaurus mati 65 juta tahun lalu memberi atau mengambil beberapa tahun?) Jadi, mengapa Anda mengatakan bahwa mereka harus dihindari?
Mike Nakis
Mike, saya pikir kekhawatirannya adalah dengan FP matematika yang pasti terhenti karena mengkonversi dari desimal ke nilai biner. Sebagai contoh, 0,3 adalah desimal berulang ketika dinyatakan sebagai nomor FP biner, dan karena itu tidak dapat direpresentasikan secara tepat. Bukan karena Anda kehilangan kapasitas, tetapi Anda kehilangan presisi.
Michael Blackburn
2

Singkatnya, karena kebanyakan tipe waktu berbasis komputer difokuskan pada penanganan masalah waktu dan zona waktu dengan benar.

Ada 2 kasus tepi yang tidak dilayani dengan baik oleh pendekatan yang biasa. Mengatur titik waktu yang ada di sisi lain dari perubahan penghematan siang hari menggunakan waktu lokal, yang kemudian akan dikonversi di UTC oleh lapisan abstraksi yang lebih rendah, dan kemudian membuat Anda 1 jam lebih awal / terlambat untuk pertemuan Anda.

Yang lain adalah (sesuai pertanyaan) memodelkan informasi tanggal sewenang-wenang, seperti mencatat tanggal lahir seseorang. Bayangkan kasus di mana dua orang dilahirkan pada saat yang sama, satu di Selandia Baru, yang lain di Hawaii. Kemungkinannya adalah bahwa mereka akan memiliki tanggal lahir yang berbeda pada paspor mereka, dan jika orang yang lahir di Hawaii pindah ke Selandia Baru, mereka akan dianggap satu hari lebih tua dari orang yang lahir di Selandia Baru, meskipun telah hidup untuk waktu yang sama persis.

Saran dalam pertanyaan sebagai pengaturan tanggal memiliki waktu tengah hari, UTC akan berfungsi, HAMPIR di mana-mana. Offset UTC berkisar dari -12 hingga +14, jadi ada beberapa tempat di Pasifik di mana pendekatan ini akan gagal. Saya cenderung memperlakukan tipe data ini sebagai string, dalam format yyyymmdd, dan jika saya harus melakukan perhitungan perbandingan antara dua tanggal, ini dapat dengan aman dilakukan sebagai perbandingan string. Saat melakukan perbandingan delta (mis. Antara tanggal dan sekarang, atau berapa lama sampai mencapai usia X), Anda perlu memastikan bahwa semua tanggal dibuat dalam offset UTC yang sama, dan kemudian dapat menggunakan fungsi waktu standar untuk melakukan pekerjaan.

Michael Shaw
sumber
3
" Saya cenderung memperlakukan tipe data ini sebagai string, dalam format yyyymmdd, dan jika saya harus melakukan perhitungan perbandingan antara dua tanggal, ini dapat dengan aman dilakukan sebagai perbandingan string. " Itu benar-benar terdengar seperti Datetipe data, hanya dibawa dalam aString
Ross Patterson
Seperti yang Anda katakan, ini adalah representasi string dari sebuah tanggal, dan tidak seperti poster aslinya, tanggal tersebut tidak dapat diubah dengan berada di zona waktu UTC + 13.
Michael Shaw
2

Mengapa tidak ada tipe data "Hanya-Tanggal" yang sebenarnya?

Untuk alasan yang sama, saya pikir, bahwa nilai DateTime umumnya ditentukan dalam UTC: kesederhanaan dan keandalan . Titik nilai DateTime adalah untuk menentukan satu titik waktu yang tidak terpengaruh oleh zona waktu, penghematan siang hari, kalender, dan penyesuaian lokal lainnya. Nilai DateTime menentukan satu instan (hingga batas resolusi jenis), bukan periode waktu atau serangkaian waktu. Batasan ini memungkinkan untuk membandingkan nilai DateTime dengan cara yang andal, dapat diprediksi, dan tidak rumit.

Mencoba menentukan tanggal dengan nilai DateTime seperti mencoba menggunakan titik untuk menentukan area.Anda dapat membuat itu bekerja dengan menggunakan konvensi, seperti "titik ini mewakili pusat lingkaran dengan radius 100m," tetapi ada banyak masalah di sana: semua orang perlu menggunakan konvensi yang sama, Anda perlu menulis banyak kode pendukung untuk membuat bekerja dengan jenis yang salah tidak terlalu menyakitkan, dan cukup dijamin bahwa pada titik tertentu Anda harus menentukan area yang lebih besar atau lebih kecil dari area konvensional. Begitu pula dengan tanggal: Anda dapat menggunakan 'siang' sebagai waktu konvensional untuk menentukan tanggal, tetapi kemudian Anda masuk ke zona waktu karena orang-orang berharap untuk menentukan tanggal dalam waktu lokal mereka daripada UTC. Dan bahkan jika Anda menemukan cara yang memuaskan untuk menggunakan DateTime untuk menentukan tanggal, Anda akan memerlukan lebih banyak informasi untuk mengetahui apakah itu merupakan tanggal absolut atau relatif: apakah tanggal 4 Juli, 1776 atau setiap 4 Juli? Bagaimana jika Anda ingin mengulang menggunakan periode lain? Dan kalender memiliki segala macam masalah gila: beberapa bulan lebih lama dari yang lain, beberapa tahun lebih lama dari yang lain, beberapa hari bahkan lebih lama dari yang lain, dan beberapa kalender memiliki celah di dalamnya. Anda tidak ingin menyelesaikan masalah ini hanya sepanjang hari, karena masalah yang sama muncul untuk periode yang lebih pendek: Anda mungkin ingin dapat menulis kode yang menyatakan "minum 1 pil setiap 4 jam" semudah "yang grup bertemu setiap Jumat ketiga. "

Jadi, ada banyak komplikasi yang terlibat dalam bekerja dengan kencan. Ini relatif (tidak ada kata pun dimaksudkan) mudah untuk memberikan jenis yang menentukan titik waktu dan bekerja dengannya seperti yang Anda lakukan angka, tetapi sangat sulit untuk menyediakan jenis yang membahas semua cara tanggal digunakan.

Seperti yang orang lain tunjukkan, di sana yang bahasa dan perpustakaan yang memberikan dukungan yang baik untuk tanggal, dan itu sering ide yang baik untuk menggunakan mereka diberikan itu cukup sulit untuk mendapatkan kode tanggal-terkait tepat.

Caleb
sumber
2
"Sulit untuk memberikan tipe yang membahas semua cara tanggal digunakan." Benar, itulah sebabnya itu adalah ide yang mengerikan untuk mencoba menyediakan satu tipe untuk melakukan semuanya. Rilis Java pertama yang disediakan hanya java.util.Date dan hasilnya mengerikan. Kemudian mereka menambahkan hierarki java.util.Calendar yang kompleks dan itu tidak menjadi jauh lebih baik.
kevin cline
1
@kevincline Sepenuhnya setuju. OP tidak menentukan bahasa, jadi saya bertujuan untuk generalisasi.
Caleb
" Untuk alasan yang sama, saya pikir, bahwa nilai DateTime umumnya ditentukan dalam UTC " ... Oh, apakah itu benar. Ini tahun 2015, dan masih ada banyak kode yang ditulis menggunakan zona waktu rumah penulis :-(
Ross Patterson
1
Saya memang bertanya-tanya mengapa tidak ada konvensi yang berlaku umum tentang tanggal. "Penggunaan titik untuk mewakili suatu area" Anda dengan sempurna merangkum frustrasi saya.
Michael Blackburn
2

Mengapa tidak ada tipe data "Hanya-Tanggal" yang sebenarnya?

Ada banyak jenis seperti itu di berbagai perpustakaan untuk berbagai bahasa. Hampir pasti ada satu untuk bahasa Anda saat ini. Paket util Java memiliki API yang mengerikan untuk perhitungan waktu, tetapi pengenalan paket java.time telah membuat hidup jauh lebih baik. Lihat java.time.LocalDate, berisi nilai tahun-bulan-hari, atau java.time.MonthDay, yang hanya berisi satu bulan dan nomor hari.

kevin cline
sumber
1

Manipulasi kalender adalah salah satu aspek komputasi yang paling buruk dipahami. Seluruh buku telah ditulis tentang topik ini. @MichealBlackburn benar sekali dalam meminta datatype hanya tanggal, yang tidak menyelesaikan ke titik pada timeline, tunduk pada interpretasi ulang. Secara historis, ada perselisihan yang sah tentang arti kencan. Kita tidak perlu melihat lebih jauh dari pada pengadopsian kalender Gregorian untuk menemukan betapa rumitnya hal itu. Selain itu, tahun tidak selalu dimulai pada 1 Januari, bahkan di Eropa barat dan koloninya ( misalnya , Inggris dan Amerika Inggris memulai tahun pada 25 Maret).

Ross Patterson
sumber
1
Ini benar. Kalender FAQ yang saya kutip dalam jawaban saya adalah sumber yang bagus untuk menemukan kerumitan dan kerumitan manipulasi clandar
Michael Le Barbier Grünewald
-2

Jawaban untuk:

Yah, saya sejujurnya ingin tahu mengapa hampir setiap bahasa hanya memiliki satu tipe data untuk ini.

Alasan paling umum mungkin "karena itu tidak perlu". Jika Anda menginginkan waktu kencan yang tidak peduli dengan jam, menit, detik, dll, maka Anda hanya perlu menginisialisasi seperti ini:

date = new DateTime(year, month, day, 0, 0, 0);

Jika mau, Anda dapat memperpanjang DateTime sendiri:

public class Date extends DateTime {
    ...
    public Date(int year, int month, int day) {
        this(year, month, day, 0, 0, 0);
    }
}

Catatan: Saya sengaja mengabaikan waktu dan zona waktu default. Tidak masalah apa yang Anda tetapkan, asalkan semuanya sama untuk semuaDate . Anda dapat membuat kasing untuk UTC. Anda dapat membuat case untuk menggunakan zona waktu yang diduduki oleh server Anda - atau saya pikir itu tidak penting untuk mewakili nilai yang tidak tepat Date. Sama dengan waktu default - Anda dapat membuatnya 0, Anda dapat membuatnya siang. Itu tidak masalah. Jika Facebook mengirimi saya pemberitahuan ulang tahun pada pukul 00:01 tetapi saya lahir pada pukul 23:59, saya tidak begitu peduli, dan saya tidak akan tersinggung karena mereka lebih dari 12 jam libur.

Di atas adalah di Jawa tetapi akan bekerja sama dalam bahasa apa pun dengan DateTimedan warisan. Java sebenarnya memiliki banyak cara untuk menyelesaikan ini, dan hal di atas sudah usang (mereka ingin Anda gunakan Calendarsekarang). Tapi seperti orang lain diposting dalam komentar, beberapa bahasa sebenarnya melakukan memberikanDate kelas, mungkin hanya untuk alasan ini.

Dalam semua kemungkinan, setiap Dateimplementasi mungkin hanya pembungkus untuk bahasa DateTimedan itu nol waktu. Kalau tidak, Anda akan membutuhkan kode duplikat untuk menyelesaikan masalah seperti jumlah hari antara dua Tanggal / DateTimes, atau apakah keduanya Datesama (Bagaimana dengan 29 Februari dan 1 Maret?). Hal-hal semacam itu biasanya diselesaikan di DateTimekelas. Masuk akal untuk menggunakan kembali kode yang sama untuk Date.

Shaz
sumber
4
-1: Gunakan LocalDate jika Anda hanya ingin tahun + bulan + hari. Menggunakan DateTime untuk tujuan itu akan mengarah ke bug ketika beberapa programmer lain melihat DateTime dan menganggap itu mewakili momen dalam waktu.
kevin cline
@ kevincline Saya tidak merasa itu perlu karena pertanyaan ini adalah agnostik bahasa. Saya juga berpikir itu jelas bahwa menggunakan kode yang berlabel "Deprecated" adalah skenario use-at-your-own-risk. Lebih penting lagi, saya hanya menggunakannya sebagai contoh dari sesuatu yang dapat Anda lakukan dalam skenario di mana bahasa tidak memilikiLocalDate , atau Datekelas ketik dan Anda harus 'roll-your-own'.
Shaz
1
Tetapi "itu perlu" untuk kode yang jelas dan benar yang melibatkan aturan bisnis tentang waktu (sebagai lawan dari waktu fisik). jika pustaka tidak menyediakan tipe untuk waktu nominal, programmer akan perlu menemukannya, dan cara melakukannya tidak dimulai dengan "DateTime".
kevin cline
@ kevincline Saya tidak melihat bagaimana kodenya menjadi kurang jelas atau ringkas. Apa perbedaan dari sudut pandang programmer antara new Date(2000, 1, 1);dan new Date(2000, 1, 1);? Bisakah Anda tahu mana yang memiliki jam, menit, dan detik kosong di bawahnya? Jika Anda khawatir tentang fungsi-fungsi tambahan yang muncul (seperti setMinutes ()), maka Anda bisa pergi rute memiliki Datebungkus DateTimealih-alih mewarisi darinya, dan kemudian Anda hanya mengekspos setYear, setMonth, setDay, dll. Dan tentu saja tidak kurang benar daripada DateTime perpustakaan yang Anda gunakan.
Shaz
Latar belakang saya sebagian besar C #, yang tidak memiliki konstruksi analog dengan LocalDate. Kami baru saja DateTime dan kacau, rupanya.
Michael Blackburn