Differenza tra 2 date in SQLite


110

Come ottengo la differenza di giorni tra 2 date in SQLite? Ho già provato qualcosa di simile:

SELECT Date('now') - DateCreated FROM Payment

Restituisce 0 ogni volta.

Risposte:


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

10
Si noti che, nonostante ciò che il nome della funzione potrebbe far pensare, ha una granularità maggiore rispetto ai giorni. È un numero di giorni, ma può essere frazionario.
Lindes,

10
Tieni presente che julianday restituisce il numero (frazionario) di "giorni", ovvero periodi di 24 ore, a partire da mezzogiorno UTC della data di origine. Di solito non è quello che ti serve, a meno che tu non viva 12 ore a ovest di Greenwich. Ad esempio, se vivi a Londra, questa mattina è lo stesso julianday di ieri pomeriggio.
JulianSymes

2
Funziona se sei DateCreatedin UTC. Se, invece, è l'ora locale, devi convertirla julianday('now')in ora locale. Non sono riuscito a trovare da nessuna parte che contenesse queste informazioni. Se ti julianday('now') - julianday(DateCreated)piace che questo post suggerisce con una data memorizzata nell'ora locale, la tua risposta sarà diversa dal tuo offset dal GMT e sarà sbagliata. Anche se forse non è la migliore pratica per memorizzare le date nell'ora locale, può comunque accadere in app in cui i fusi orari non contano (tranne quando lo strumento con cui stai lavorando li impone su di te, come qui).
vapcguy

3
Con l'ipotesi che DateCreated sia nell'ora locale, se lo fai julianday('now') - julianday(DateCreated, 'utc'), per rendere sia UTC, non funziona allo stesso modo di farlo julianday('now', 'localtime') - julianday(DateCreated). Il primo non tiene conto dei giorni di DST e aggiungerà un'ora in più alle date create in marzo-novembre. Quest'ultimo in realtà lo spiega. stackoverflow.com/questions/41007455/...
vapcguy

60

Differenza in giorni

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

Differenza in ore

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

Differenza in minuti

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

Differenza in secondi

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

1
per sqlite versione 3.12.0 l'espressione cast ha il TIPO AS tra parentesi. ad esempio "Seleziona Cast (5.6 As Integer);" sqlite.org/lang_expr.html#castexpr Altrimenti esempi davvero utili.
rapina il

Grazie @rob. Qualcuno ha proposto di modificarmi in quel modo prima. Ma quando l'ho provato in Sqlitebrowser, non funzionava. Forse perché è una versione precedente. Quindi l'ho tenuto così com'è ..
Sayka

Ho appena usato SQLitebrowser e ho ricevuto l'errore rob menzionato .. Posso modificare il tuo post con una formulazione moderna?
Noumenon

@Noumenon per favore proponi la tua modifica. Lo controllerò in sqlitebrowser qui e se funziona, approverò sicuramente la tua modifica. Grazie per il tuo tempo.
Sayka

2
Questa risposta è molto più ricca di funzionalità rispetto alla risposta accettata, IMHO.
Marcus Parsons

33

Entrambe le risposte forniscono soluzioni un po 'più complesse, come devono essere. Supponiamo che il pagamento sia stato creato il January 6, 2013. E vogliamo conoscere la differenza tra questa data e quella odierna.

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

La differenza è di 34 giorni. Possiamo usare julianday('now')per una migliore chiarezza. In altre parole, non abbiamo bisogno di mettere date()o datetime()funzioni come parametri per julianday() funzionare.


Non ne sono sicuro, ma se questo comando era in codice e il valore 6 gennaio 2013 proveniva dal database, è necessario considerare il tipo di dati utilizzato.
NoChance

23

La documentazione di SQLite è un ottimo riferimento e la pagina DateAndTimeFunctions è buona da aggiungere ai segnalibri.

È anche utile ricordare che è abbastanza facile giocare con le query con l'utilità della riga di comando sqlite:

sqlite> select julianday(datetime('now'));
2454788.09219907
sqlite> select datetime(julianday(datetime('now')));
2008-11-17 14:13:55

1
Poiché questa pagina viene fornita con un posizionamento nei motori di ricerca di Google, ecco il link corrente: sqlite.org/lang_datefunc.html
markusN

9

Questa risposta è un po 'prolissa e la documentazione non te lo dirà (perché presumono che tu stia memorizzando le tue date come date UTC nel database), ma la risposta a questa domanda dipende in gran parte dal fuso orario in cui le tue date sono memorizzate in. Inoltre, non si utilizza Date('now'), ma si utilizza la julianday()funzione, per calcolare entrambe le date rispetto a una data comune, quindi sottrarre la differenza di tali risultati l'uno dall'altro.

Se le tue date sono memorizzate in UTC:

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

Questo è ciò che ha la risposta in cima alla classifica ed è anche nella documentazione . È solo una parte dell'immagine, e una risposta molto semplicistica, se me lo chiedi.

Se le tue date sono memorizzate nell'ora locale, l'utilizzo del codice sopra renderà la tua risposta SBAGLIATA per il numero di ore in cui il tuo offset GMT è. Se ti trovi negli Stati Uniti orientali come me, che è GMT -5, il tuo risultato avrà 5 ore in più. E se provi a renderti DateCreatedconforme a UTC perché julianday('now')va contro una data GMT:

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

Questo ha un bug in cui aggiungerà un'ora per un DateCreatedche è durante l'ora legale (marzo-novembre). Supponi che "adesso" sia a mezzogiorno in un giorno non DST e che hai creato qualcosa a giugno (durante l'ora legale) a mezzogiorno, il risultato darà 1 ora di distanza, invece di 0 ore, per la parte delle ore. Dovresti scrivere una funzione nel codice dell'applicazione che visualizza il risultato per modificare il risultato e sottrarre un'ora dalle date dell'ora legale. L'ho fatto, fino a quando non ho capito che c'era una soluzione migliore a quel problema che stavo avendo: SQLite vs Oracle - Calcolo delle differenze di data - ore

Invece, come mi è stato fatto notare, per le date memorizzate nell'ora locale, fai corrispondere entrambe all'ora locale:

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

Oppure aggiungi 'Z'all'ora locale:

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

Entrambi sembrano compensare e non aggiungere l'ora extra per le date dell'ora legale e fare una sottrazione diretta - in modo che l'elemento creato a mezzogiorno in un giorno dell'ora legale, quando si controlla a mezzogiorno in un giorno non ora legale, non riceverà un'ora in più quando eseguire il calcolo.

E mentre riconosco che la maggior parte dirà di non memorizzare le date nell'ora locale nel database e di memorizzarle in UTC in modo da non incappare in questo, beh non tutte le applicazioni hanno un pubblico mondiale e non tutti i programmatori vogliono per passare attraverso la conversione di OGNI data nel loro sistema in UTC e viceversa ogni volta che eseguono un GET o SET nel database e si occupano di capire se qualcosa è locale o in UTC.


"È solo una parte dell'immagine, e una risposta molto semplicistica, se me lo chiedi." Si hai ragione. Ma la mia risposta è stata data 3 minuti dopo che ha posto la sua domanda, quando la tua arriva due anni dopo. Semplicistico ma lei sembrava adattarsi a lui.
Fred

1
@Fred abbastanza giusto. Ma in realtà ha finito per portarmi a fare un giro, come ho descritto sopra, e quindi non mi ha aiutato. Volevo essere sicuro che chiunque l'avesse visto in futuro sapesse esattamente cosa stava succedendo in modo da non incappare nelle stesse trappole che ho fatto io - o, se lo avessero fatto, avrebbero saputo come uscirne.
vapcguy

@Fred, questa è un'ottima spiegazione e non sono sicuro di cosa aspettarti? Forse pubblicare la tua risposta?
NoChance

Grazie per la tua spiegazione. Non sono sicuro che le persone di SQLite abbiano deciso di andare contro gli standard che le persone hanno imparato ad accettare nel corso degli anni e si sono ritrovate con un'implementazione inutilmente complessa e difficile da testare in un aspetto critico come la data e l'ora! Immagina che il numero di casi di test richiesti per verificare che ogni data nell'applicazione funzioni come gli esseri umani si aspettano!
NoChance

3

Solo una nota per scrivere le funzioni dell'orologio. Per coloro che cercano le ore lavorate, una modifica molto semplice di questo consente di visualizzare le ore più i minuti come percentuale di 60 come la maggior parte delle aziende di libro paga lo desidera.

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

Neat piccola domanda, tuttavia, però :)
vapcguy

3

Se vuoi l'ora nel formato 00:00: l'ho risolto in questo modo:

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

2

Dato che il formato della data è il seguente: "AAAA-MM-GG HH: MM: SS", se devi trovare la differenza tra due date in numero di mesi:

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


2

In primo luogo, non è chiaro quale sia il formato della data. C'è già una risposta coinvolgente strftime("%s").

Mi piace espandere questa risposta.

SQLite ha solo le seguenti classi di archiviazione: NULL, INTEGER, REAL, TEXT o BLOB. Per semplificare le cose, presumo che le date siano REALI contenenti i secondi dal 1970-01-01. Ecco uno schema di esempio per il quale inserirò i dati di esempio del "1 dicembre 2018":

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

Ora calcoliamo la differenza di data tra il "1 ° dicembre 2018" e ora (mentre scrivo, è mezzogiorno del 12 dicembre 2018):

Differenza di data in giorni:

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

Differenza di data in ore:

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

Differenza di data in minuti:

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

Differenza di data in secondi:

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

2

Se vuoi la differenza in pochi secondi

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

0

Se vuoi registrare tra giorni,

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

0

Nel mio caso, devo calcolare la differenza in minuti e julianday()non fornisce un valore preciso. Invece, utilizzo strftime():

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

Entrambe le date vengono convertite in unixtime (secondi), quindi sottratte per ottenere il valore in secondi tra le due date. Quindi, dividerlo per 60.

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.