Bagaimana cara kerja nilai DATETIME di SQLite?

110

Saya membuat aplikasi Android dan perlu menyimpan tanggal / waktu catatan pembuatan. Dokumen SQLite mengatakan, bagaimanapun, "SQLite tidak memiliki kelas penyimpanan yang disisihkan untuk menyimpan tanggal dan / atau waktu" dan "mampu menyimpan tanggal dan waktu sebagai nilai TEXT, REAL, atau INTEGER".

Apakah ada alasan teknis untuk menggunakan satu jenis di atas jenis lainnya? Dan dapatkah satu kolom menyimpan tanggal dalam salah satu dari tiga format dari baris ke baris?

Saya perlu membandingkan tanggal nanti. Misalnya, di aplikasi saya, saya akan menampilkan semua rekaman yang dibuat antara tanggal A hingga tanggal B. Saya khawatir bahwa tidak memiliki kolom DATETIME yang benar dapat mempersulit perbandingan.

Khairil Ushan
sumber

Jawaban:

83

SQlite tidak memiliki tipe datetime tertentu. Anda dapat menggunakan TEXT, REALatau INTEGERmengetik, mana saja yang sesuai dengan kebutuhan Anda.

Langsung dari DOCS

SQLite tidak memiliki kelas penyimpanan yang dikhususkan untuk menyimpan tanggal dan / atau waktu. Sebagai gantinya, Fungsi Tanggal dan Waktu bawaan dari SQLite mampu menyimpan tanggal dan waktu sebagai nilai TEXT, REAL, atau INTEGER:

  • TEXT sebagai string ISO8601 ("YYYY-MM-DD HH: MM: SS.SSS").
  • NYATA sebagai angka hari Julian, jumlah hari sejak tengah hari di Greenwich pada 24 November 4714 SM menurut kalender proleptik Gregorian.
  • INTEGER sebagai Unix Time, jumlah detik sejak 1970-01-01 00:00:00 UTC.

Aplikasi dapat memilih untuk menyimpan tanggal dan waktu dalam salah satu format ini dan dengan bebas mengkonversi antar format menggunakan fungsi tanggal dan waktu bawaan.

Fungsi Tanggal dan Waktu bawaan SQLite dapat ditemukan di sini .

neo108
sumber
11
Penting untuk diperhatikan - semua metode penyimpanan tanggal menggunakan format yang dapat dibandingkan menggunakan operator standar =, <,> dan ANTARA.
Larry Lustig
2
"SQLite tidak memiliki kelas penyimpanan yang dikhususkan untuk menyimpan tanggal dan / atau waktu" - kecuali SQLite memiliki tipe DATE dan DATETIME yang tidak pernah disebutkan dalam dokumentasi
Slabko
12
@ Slabko Itu tidak. SQLite mengizinkan apa pun (termasuk DATETIME) sebagai tipe kolom yang dideklarasikan. Berdasarkan hal tersebut, kolom tersebut memiliki afinitas dengan kelas penyimpanan (bahkan memiliki contoh cara kerjanya untuk DATETIME dalam dokumentasi). Afinitas itu lebih seperti petunjuk, karena setiap entri kolom sebenarnya dapat memiliki kelas penyimpanan yang berbeda. Kelas penyimpanan masih selangkah lebih lemah dari satu jenis dan dapat didukung oleh berbagai jenis. Jadi ya, Anda bisa menggunakan DATETIME. Tidak, itu sebenarnya tidak mendukungnya sebagai tipe atau kelas penyimpanan. Ya, dokumentasinya sebenarnya mengandung kata "DATETIME".
Jasper
20

SQLite tidak memiliki kelas penyimpanan yang dikhususkan untuk menyimpan tanggal dan / atau waktu. Sebagai gantinya, Fungsi Tanggal dan Waktu bawaan dari SQLite mampu menyimpan tanggal dan waktu sebagai nilai TEXT, REAL, atau INTEGER:

TEXT sebagai string ISO8601 ("YYYY-MM-DD HH: MM: SS.SSS"). NYATA sebagai angka hari Julian, jumlah hari sejak tengah hari di Greenwich pada 24 November 4714 SM menurut kalender proleptik Gregorian. INTEGER sebagai Unix Time, jumlah detik sejak 1970-01-01 00:00:00 UTC. Aplikasi dapat memilih untuk menyimpan tanggal dan waktu dalam salah satu format ini dan dengan bebas mengkonversi antar format menggunakan fungsi tanggal dan waktu bawaan.

Karena itu, saya akan menggunakan INTEGER dan menyimpan detik sejak Unix epoch (1970-01-01 00:00:00 UTC).

Diego Torres Milano
sumber
1
Saya lebih suka ini juga. Kelas terkait tanggal / waktu standar didukung secara internal oleh long, dan cukup mudah untuk membandingkan long.
Karakuri
1
@dtmilano Mengapa Anda lebih memilih INTEGER di sini daripada String?
IgorGanapolsky
1
INTEGER hanya menggunakan 8 byte, TEXT menggunakan 23 byte dalam contoh ini. Tidak jelas bagaimana memilih tipe penyimpanan datanya. Apakah ini berarti jika saya membuat kolom bertipe INTEGER, fungsinya akan otomatis disimpan sebagai Unix Time?
rayzinnz
2
REAL menggunakan 8 byte juga. Epoch detik akan menjadi 10 digit hingga akhir 2286, dan karena IEEE double mendukung 15-17 digit signifikan , ini memberi Anda resolusi yang lebih baik daripada resolusi milidetik. RSQLitetampaknya beralih POSIXctke zaman numerik, jadi ini berfungsi cukup baik untuk saya.
r2evans
@ r2evans Saya tidak yakin apa yang Anda katakan. Jika saya ingin menyimpan milidetik sejak Epoch, bagaimana cara melakukannya?
Michael
14

Salah satu fitur canggih dari SQLite adalah memungkinkan Anda memilih jenis penyimpanan. Keuntungan / kerugian masing-masing dari tiga kemungkinan yang berbeda:

  • String ISO8601

    • Perbandingan string memberikan hasil yang valid
    • Menyimpan pecahan detik, hingga tiga digit desimal
    • Membutuhkan lebih banyak ruang penyimpanan
    • Anda akan langsung melihat nilainya saat menggunakan browser database
    • Perlu parsing untuk kegunaan lain
    • Pengubah kolom "default current_timestamp" akan disimpan menggunakan format ini
  • Bilangan riil

    • Presisi tinggi dalam hitungan detik
    • Rentang waktu terlama
  • Bilangan bulat

    • Ruang penyimpanan terendah
    • Operasi cepat
    • Rentang waktu kecil
    • Kemungkinan masalah tahun 2038

Jika Anda perlu membandingkan berbagai jenis atau mengekspor ke aplikasi eksternal, Anda bebas menggunakan fungsi konversi datetime SQLite sesuai kebutuhan.

Zso
sumber
1
Mengapa ada masalah 2038? INTEGER tampaknya mendukung penyimpanan 64 bit.
guan boshen
1
@guanboshen Sejauh yang saya tahu, satu-satunya alasan untuk khawatir tentang 2038 adalah dukungan pada platform host. Dokumentasi SQLite mengklaim menggunakan C localtime_r()( sqlite.org/lang_datefunc.html#caveats_and_bugs ) dalam implementasi referensi, dan localtime()berpotensi rentan terhadap 2038 jika platform host memiliki 32-bit time_t. Yang mengatakan, karena SQLite mengklaim untuk menjaga kemungkinan ini dengan memetakan tanggal di luar ke dalam rentang pra-konversi yang aman (lihat tautan yang sama), saya pikir itu tidak mungkin menjadi masalah kecuali mungkin dalam kasus esoterik.
Zoe Sparks
@ ZoëSparks Terima kasih atas klarifikasi Anda.
guan boshen
7

Untuk hampir semua masalah tanggal dan waktu, saya lebih suka menyederhanakan banyak hal, sangat, sangat sederhana ... Hingga detik disimpan dalam bilangan bulat.

Bilangan bulat akan selalu didukung sebagai bilangan bulat dalam database, file datar, dll. Anda melakukan sedikit matematika dan memasukkannya ke jenis lain dan Anda dapat memformat tanggal sesuai keinginan Anda.

Dengan cara ini, Anda tidak perlu khawatir ketika [masukkan database favorit saat ini di sini] diganti dengan [database favorit masa depan] yang kebetulan tidak menggunakan format tanggal yang Anda pilih hari ini.

Ini hanya sedikit overhead matematika (mis. Metode - membutuhkan dua detik, saya akan memposting intinya jika perlu) dan menyederhanakan banyak hal untuk banyak operasi terkait tanggal / waktu nanti.

KelvinEWilliams
sumber
7

Simpan di bidang tipe long. Lihat Date.getTime()dannew Date(long)

koem
sumber
bagaimana saya bisa membandingkannya ?? dapatkah kamu memberi saya contoh pertanyaan ..: D
Khairil Ushan
Lihatlah Joda Time untuk perbandingan dalam kode ( joda-time.sourceforge.net ) dan gunakan perbandingan panjang sederhana dalam SQL (misalnya perbandingan numerik).
Sintaks
pilih * dari tabel tempat pembuatan antara a dan b;
koem