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.

Jawaban:


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

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)

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.


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

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.


"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

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

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))


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

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')

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;

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

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.