Cara terbaik untuk menangani tanggal sebelum 1000 AD di MySQL?

9

Saya membuat database untuk catatan yang melampaui sebelum 1000 AD, tetapi bidang MySQL Date dan DateTime hanya mendukung tanggal mulai 1000.

Apakah ada cara yang lebih nyaman daripada menggunakan tipe bigint untuk menghitung detik sebelum / sesudah 1/1/1970 menggunakan cap waktu Unix, atau beralih ke perangkat lunak database yang mendukung rentang tanggal yang lebih besar?

David LeBauer
sumber
1
Ini dijawab dengan cukup baik di SO: stackoverflow.com/q/2487543/514119
stanleykylee
@stanleykylee terima kasih telah menunjukkannya. Pertanyaannya berbeda, tetapi masalah muncul dalam komentar dan kemudian dijawab di sepanjang baris 'pilih tanggal referensi dan gunakan bidang angka', dengan peringatan 'itu akan membosankan untuk kode, tetapi cukup mudah' dan pertanyaan saya, antara lain, apakah ini merupakan alternatif terbaik.
David LeBauer
Ah, entah bagaimana saya melewatkan itu dalam pertanyaan. Izinkan saya ke facepalm dan hapus komentar ini ...
jcolebrand

Jawaban:

7

Alternatifnya adalah menyimpan setiap bagian dari tanggal dalam bidang angka. Jadi, Anda akan memiliki tiga bidang:

year  SMALLINT     # Store positive values for AD and negative for BC years.
month TINYINT
day   TINYINT

Dengan cara ini masih bisa dibaca manusia. Kisaran nilai untuk berbagai tipe data numerik di MySQL tersedia di Ikhtisar Jenis Numerik . Persyaratan penyimpanan tersedia di Persyaratan Penyimpanan Tipe Data .

dabest1
sumber
1
Saya ingin memberi ini +1, tapi saya cukup yakin logika tanggal akan mengerikan bukan?
Camilo Martin
Bagaimana kalau memiliki satu bidang tempat kami menyimpan tanggal dalam format angka misalnya, 2015-10-12 10:12:05
atpatil11
8

Tidak ada tipe data tanggal RDBMS asli yang akan dilakukan untuk aplikasi yang memerlukan tanggal yang sangat lama (dan untuk beberapa, bahkan di masa mendatang).

Jika saya jadi Anda, saya akan menggunakan tipe string untuk penyimpanan asli dan tetap dengan format tempat-signifikan seperti: + YYYY-MM-DD untuk mengakomodasi BC / AD dan tanggal mendatang yang masuk akal secara historis atau masuk akal.

Jika mungkin membantu, Anda bisa membangun kelas perpustakaan yang mengubah format penyimpanan internal Anda menjadi yang lebih rapi untuk lapisan UI. Anda bahkan mungkin menyertakan fungsi pustaka yang mengonversi ke tipe tanggal asli, jika bahasa pilihan Anda mendukung tanggal yang akan Anda miliki di database Anda.

Joel Brown
sumber
1
Jika Anda menggunakan SQL Server 2008+, DATETIME2 adalah jawabannya . Rentang tanggal: 1 Januari, 1 M hingga 31 Desember, 9999 M.
Nick Chammas
1
Saran yang bagus Untuk sistem lain, saya juga merekomendasikan CHECKbatasan untuk menerapkan format string tanggal. Sayangnya, MySQL tidak menegakkan CHECK batasan.
Nick Chammas
2
@Nick, setuju tentang DATETIME2 di SQL Server 2008+, (saya akan melewatkan 1753) tetapi OP mulai dengan MySQL sebagai sahamnya di tanah. Juga, bahkan DATETIME2 jatuh segera setelah Anda perlu menambahkan 31 Desember, 1 SM ke kalender Anda :)
Joel Brown
1
Anda selalu dapat menambahkan kolom BITatau BOOLEANuntuk menunjukkan polaritas tanggal. :) Tentu saja, jika Anda melakukan itu, Anda sendirian jika melakukan perhitungan pada tanggal "BC" itu. Siapa yang tahu penyesuaian kalender seperti apa yang biasanya dijaga untuk kita oleh fungsi perpustakaan akan terlewatkan saat memanipulasi tanggal BC "palsu" ...
Nick Chammas
1
Mark, alasan saya merekomendasikan sebuah string adalah, selama Anda memformulasikannya dengan benar, string itu akan dapat dibaca manusia (dan bahkan sampai batas tertentu dapat diedit) tanpa pemrosesan apa pun dan Anda dapat membangun fungsi manipulasi tanggal khusus dengan relatif mudah. Menyimpan tanggal sebagai angka sangat, sangat tidak nyaman, kecuali jika Anda memiliki perpustakaan fungsi yang dapat menafsirkan pengkodean semacam itu untuk manusia biasa. Tentu saja, ketika perpustakaan seperti itu ada, pengkodean tanggal sebagai angka jauh lebih masuk akal.
Joel Brown
1

Bagaimana kalau memiliki bidang float tunggal dalam tabel di mana kami menyimpan tanggal dalam format numerik untuk misalnya 2015-10-12 10:12:05 akan disimpan 20151012. 101205. Selalu lebih baik untuk memiliki pengurutan pada bidang tunggal daripada memiliki 3 atau lebih bidang yang berbeda.

Logika di atas tidak berfungsi untuk beberapa skenario. Jadi, kami telah mengonversi tanggal menjadi Detik mengingat 1 hari = 86400 detik. Digunakan negatif untuk tanggal SM. Ini berfungsi seperti yang diharapkan.

atpatil11
sumber
1
angka negatif untuk BC?
Rob Sedgwick
1
151012 dan 150819 keduanya akan berada di 15AD, -151109 akan berada di 15BC
Rob Sedgwick