Perbedaan antara 2 tanggal di SQLite

110

Bagaimana cara mengetahui perbedaan hari antara 2 tanggal di SQLite? Saya sudah mencoba sesuatu seperti ini:

SELECT Date('now') - DateCreated FROM Payment

Ia mengembalikan 0 setiap kali.

Agustin Meriles
sumber

Jawaban:

123
 SELECT julianday('now') - julianday(DateCreated) FROM Payment;
Fred
sumber
10
Perhatikan bahwa terlepas dari apa yang mungkin dipikirkan oleh nama fungsi, ini memiliki perincian yang lebih tinggi daripada hari. Ini beberapa hari, tapi bisa pecahan.
Lindes
10
Ingatlah bahwa julianday mengembalikan jumlah (pecahan) dari 'hari' - yaitu periode 24 jam, sejak siang hari UTC pada tanggal asal. Biasanya bukan itu yang Anda butuhkan, kecuali Anda tinggal 12 jam di sebelah barat Greenwich. Misal jika Anda tinggal di London, pagi ini pada hari julianday yang sama dengan kemarin sore.
JulianSymes
2
Ini berfungsi jika Anda DateCreateddalam UTC. Sebaliknya, jika ini adalah waktu lokal, Anda harus mengonversi julianday('now')ke waktu lokal. Saya tidak dapat menemukan tempat yang memiliki informasi ini. Jika Anda julianday('now') - julianday(DateCreated)menyukai posting ini menyarankan dengan tanggal yang disimpan dalam waktu lokal, jawaban Anda akan dikesampingkan dari GMT dan akan salah. Meskipun mungkin bukan praktik terbaik untuk menyimpan tanggal dalam waktu lokal, ini masih dapat terjadi di aplikasi di mana zona waktu tidak penting (kecuali saat alat yang Anda gunakan memaksanya, seperti di sini).
vapcguy
3
Dengan asumsi DateCreated dalam waktu lokal, jika Anda melakukannya julianday('now') - julianday(DateCreated, 'utc'), untuk membuat kedua UTC, cara kerjanya tidak sama julianday('now', 'localtime') - julianday(DateCreated). Yang pertama tidak memperhitungkan hari DST dan akan menambahkan satu jam ekstra ke tanggal yang dibuat pada Mar-Nov. Yang terakhir sebenarnya menjelaskannya. stackoverflow.com/questions/41007455/…
vapcguy
60

Perbedaan Dalam Hari

Select Cast ((
    JulianDay(ToDate) - JulianDay(FromDate)
) As Integer)

Perbedaan Dalam Jam

Select Cast ((
    JulianDay(ToDate) - JulianDay(FromDate)
) * 24 As Integer)

Selisih Dalam Menit

Select Cast ((
    JulianDay(ToDate) - JulianDay(FromDate)
) * 24 * 60 As Integer)

Selisih Dalam Detik

Select Cast ((
    JulianDay(ToDate) - JulianDay(FromDate)
) * 24 * 60 * 60 As Integer)
Sayka
sumber
1
untuk sqlite versi 3.12.0 ekspresi cast memiliki AS TYPE di dalam tanda kurung. misalnya "Pilih Cast (5.6 Sebagai Integer);" sqlite.org/lang_expr.html#castexpr Atau contoh yang sangat berguna.
merampok
Terima kasih @rob. Seseorang mengusulkan untuk mengedit saya seperti itu sebelumnya. Tetapi ketika saya mencobanya di Sqlitebrowser, tidak berhasil. Mungkin itu karena versi yang lebih lama. Jadi saya menyimpannya apa adanya ..
Sayka
Saya baru saja menggunakan SQLitebrowser dan mendapatkan error rob yang disebutkan .. Bolehkah saya mengedit postingan Anda menjadi kata-kata modern?
Noumenon
@Noumenon mohon ajukan suntingan Anda. Saya akan memeriksanya di sqlitebrowser di sini dan jika berfungsi, pasti akan menyetujui suntingan Anda. Terima kasih atas waktu Anda.
Sayka
2
Jawaban ini jauh lebih berisi fitur daripada jawaban yang diterima, IMHO.
Marcus Parsons
33

Kedua jawaban tersebut memberikan solusi yang sedikit lebih kompleks, sebagaimana mestinya. Katakanlah pembayaran dilakukan pada January 6, 2013. Dan kami ingin mengetahui perbedaan antara tanggal ini dan hari ini.

sqlite> SELECT julianday() - julianday('2013-01-06');
34.7978485878557 

Perbedaannya adalah 34 hari. Kita bisa gunakan julianday('now')untuk kejelasan yang lebih baik. Dengan kata lain, kita tidak perlu meletakkan date()atau datetime()berfungsi sebagai parameter agar bisa julianday() berfungsi.

Jan Bodnar
sumber
Saya tidak yakin, tetapi jika perintah ini ada dalam kode, dan nilai 6 Jan 2013 berasal dari database, kita perlu mempertimbangkan tipe data yang digunakan.
NoChance
23

Dokumentasi SQLite adalah referensi yang bagus dan halaman DateAndTimeFunctions adalah salah satu yang bagus untuk ditandai.

Ini juga membantu untuk diingat bahwa cukup mudah untuk bermain dengan kueri dengan utilitas baris perintah sqlite:

sqlite> select julianday(datetime('now'));
2454788.09219907
sqlite> select datetime(julianday(datetime('now')));
2008-11-17 14:13:55
konverter42
sumber
1
Karena halaman ini dilengkapi dengan peringkat mesin pencari google, di sini tautan saat ini: sqlite.org/lang_datefunc.html
markusN
9

Jawaban ini agak bertele-tele, dan dokumentasinya tidak akan memberi tahu Anda hal ini (karena mereka menganggap Anda menyimpan tanggal Anda sebagai tanggal UTC di database), tetapi jawaban untuk pertanyaan ini sangat bergantung pada zona waktu tempat tanggal Anda disimpan di. Anda juga tidak menggunakan Date('now'), tetapi menggunakan julianday()fungsi tersebut, untuk menghitung kedua tanggal mundur terhadap tanggal yang sama, lalu kurangi selisih hasil tersebut satu sama lain.

Jika tanggal Anda disimpan dalam UTC:

SELECT julianday('now') - julianday(DateCreated) FROM Payment;

Inilah yang dimiliki jawaban peringkat teratas, dan juga ada dalam dokumentasi . Itu hanya sebagian dari gambaran, dan jawaban yang sangat sederhana, jika Anda bertanya kepada saya.

Jika tanggal Anda disimpan dalam waktu lokal, menggunakan kode di atas akan membuat jawaban Anda SALAH menurut jumlah jam offset GMT Anda. Jika Anda berada di AS bagian Timur seperti saya, yaitu GMT -5, hasil Anda akan ditambahkan 5 jam ke dalamnya. Dan jika Anda mencoba DateCreatedmenyesuaikan dengan UTC karena julianday('now')bertentangan dengan tanggal GMT:

SELECT julianday('now') - julianday(DateCreated, 'utc') FROM Payment;

Ini memiliki bug di mana ia akan menambahkan satu jam untuk DateCreateditu selama Daylight Savings Time (Maret-November). Katakanlah bahwa "sekarang" adalah siang hari pada hari non-DST, dan Anda membuat sesuatu di bulan Juni (selama DST) pada siang hari, hasil Anda akan memberikan selisih 1 jam, bukan 0 jam, untuk bagian jam. Anda harus menulis fungsi dalam kode aplikasi Anda yang menampilkan hasil untuk mengubah hasil dan mengurangi satu jam dari tanggal DST. Saya melakukan itu, sampai saya menyadari ada solusi yang lebih baik untuk masalah yang saya alami: SQLite vs. Oracle - Menghitung perbedaan tanggal - jam

Sebaliknya, seperti yang ditunjukkan kepada saya, untuk tanggal yang disimpan dalam waktu lokal, buat keduanya cocok dengan waktu setempat:

SELECT julianday('now', 'localtime') - julianday(DateCreated) FROM Payment;

Atau tambahkan 'Z'waktu setempat:

julianday(datetime('now', 'localtime')||'Z') - julianday(CREATED_DATE||'Z')

Kedua hal tersebut seakan mengimbangi dan tidak menambah jam ekstra untuk tanggal DST dan melakukan pengurangan langsung - sehingga barang yang dibuat pada siang hari pada hari DST, saat dilakukan pengecekan pada siang hari pada hari non-DST, tidak akan mendapat jam ekstra saat melakukan perhitungan.

Dan sementara saya tahu sebagian besar akan mengatakan jangan simpan tanggal dalam waktu lokal di database Anda, dan menyimpannya di UTC sehingga Anda tidak mengalami hal ini, tapi tidak setiap aplikasi memiliki audiens di seluruh dunia, dan tidak setiap programmer menginginkannya. untuk melalui konversi SETIAP tanggal dalam sistem mereka ke UTC dan kembali lagi setiap kali mereka melakukan GET atau SET di database dan berurusan dengan mencari tahu apakah sesuatu itu lokal atau dalam UTC.

vapcguy
sumber
"Itu hanya sebagian dari gambaran, dan jawaban yang sangat sederhana, jika Anda bertanya kepada saya." Ya kamu benar. Tetapi jawaban saya diberikan 3 menit setelah dia menanyakan pertanyaannya ketika pertanyaan Anda datang dua tahun kemudian. Sederhana tapi sepertinya dia cocok untuknya.
Fred
1
@Red Cukup adil. Tapi itu akhirnya membawa saya jalan-jalan, seperti yang saya jelaskan di atas, dan karenanya tidak membantu saya. Saya ingin memastikan siapa pun yang melihat ini di masa mendatang tahu persis apa yang sedang terjadi sehingga mereka tidak mengalami kesulitan yang sama dengan yang saya lakukan - atau, jika mereka melakukannya, mereka akan tahu cara keluar dari mereka.
vapcguy
@Fred, ini adalah penjelasan yang sangat bagus dan saya tidak yakin apa yang diharapkan? Mungkin memposting jawaban Anda?
NoChance
Terima kasih atas penjelasan Anda. Saya tidak yakin orang-orang SQLite memutuskan untuk melawan standar yang diterima orang-orang selama bertahun-tahun dan berakhir dengan implementasi yang tidak perlu rumit dan sulit untuk diuji dalam aspek kritis seperti tanggal dan waktu! Bayangkan jumlah kasus uji yang diperlukan untuk memverifikasi setiap tanggal dalam aplikasi berfungsi seperti yang diharapkan manusia!
NoChance
3

Sekadar catatan untuk menulis fungsi timeclock. Bagi mereka yang mencari jam kerja, perubahan yang sangat sederhana adalah jam ditambah menit ditampilkan sebagai persentase dari 60 seperti yang diinginkan sebagian besar perusahaan penggajian.

CAST ((julianday(clockOUT) - julianday(clockIN)) * 24 AS REAL) AS HoursWorked

Clock In            Clock Out           HoursWorked
2016-08-07 11:56    2016-08-07 18:46    6.83333332836628
Gary
sumber
Pertanyaan kecil yang rapi, bagaimanapun, :)
vapcguy
3

Jika Anda menginginkan waktu dalam format 00:00: Saya menyelesaikannya seperti itu:

select strftime('%H:%M',CAST ((julianday(FinishTime) - julianday(StartTime)) AS REAL),'12:00') from something
Matas Lesinskas
sumber
2

Mengingat bahwa format tanggal Anda mengikuti: "YYYY-MM-DD HH: MM: SS", jika Anda perlu menemukan perbedaan antara dua tanggal dalam jumlah bulan:

(strftime('%m', date1) + 12*strftime('%Y', date1)) - (strftime('%m', date2) + 12*strftime('%Y', date2))

Ashish Koshy
sumber
2

Pertama, tidak jelas apa format tanggal Anda. Sudah ada jawaban yang melibatkan strftime("%s").

Saya ingin memperluas jawaban itu.

SQLite hanya memiliki kelas penyimpanan berikut: NULL, INTEGER, REAL, TEXT atau BLOB. Untuk menyederhanakan, saya akan berasumsi tanggal NYATA berisi detik sejak 1970-01-01. Berikut adalah contoh skema yang akan saya masukkan ke dalam contoh data "1 Desember 2018":

CREATE TABLE Payment (DateCreated REAL);
INSERT INTO Payment VALUES (strftime("%s", "2018-12-01"));

Sekarang mari kita cari tahu perbedaan tanggal antara "1 Desember 2018" dan sekarang (saat saya menulis ini, sekarang adalah tengah hari 12 Desember 2018):

Perbedaan tanggal dalam hari:

SELECT (strftime("%s", "now") - DateCreated) / 86400.0 FROM Payment;
-- Output: 11.066875

Perbedaan tanggal dalam jam:

SELECT (strftime("%s", "now") - DateCreated) / 3600.0 FROM Payment;
-- Output: 265.606388888889

Perbedaan tanggal dalam menit:

SELECT (strftime("%s", "now") - DateCreated) / 60.0 FROM Payment;
-- Output: 15936.4833333333

Perbedaan tanggal dalam hitungan detik:

SELECT (strftime("%s", "now") - DateCreated) FROM Payment;
-- Output: 956195.0
Stephen Quan
sumber
2

Jika Anda menginginkan perbedaan dalam hitungan detik

SELECT strftime('%s', '2019-12-02 12:32:53') - strftime('%s', '2019-12-02 11:32:53')
Sandris B
sumber
0

Jika Anda ingin rekaman di antara hari-hari,

select count(col_Name) from dataset where cast(julianday("now")- julianday(_Last_updated) as int)<=0;
Rakesh Chaudhari
sumber
0

Dalam kasus saya, saya harus menghitung perbedaan dalam menit dan julianday()tidak memberikan nilai yang akurat. Sebagai gantinya, saya menggunakan strftime():

SELECT (strftime('%s', [UserEnd]) - strftime('%s', [UserStart])) / 60

Kedua tanggal diubah menjadi waktu unix (detik), kemudian dikurangi untuk mendapatkan nilai dalam hitungan detik antara kedua tanggal tersebut. Selanjutnya, bagi dengan 60.

https://www.sqlite.org/cvstrac/wiki?p=DateAndTimeFunctions

Yusril Maulidan Raji
sumber