Unterschied zwischen 2 Daten in SQLite

110

Wie erhalte ich die Differenz in Tagen zwischen zwei Daten in SQLite? Ich habe schon so etwas ausprobiert:

SELECT Date('now') - DateCreated FROM Payment

Es wird jedes Mal 0 zurückgegeben.

Agustin Meriles
quelle

Antworten:

123
 SELECT julianday('now') - julianday(DateCreated) FROM Payment;
Fred
quelle
10
Beachten Sie, dass dies trotz des möglichen Funktionsnamens eine höhere Granularität als Tage aufweist. Es ist eine Anzahl von Tagen, kann aber ein Bruchteil sein.
Lindes
10
Beachten Sie, dass julianday die (gebrochene) Anzahl von 'Tagen' zurückgibt - dh 24-Stunden-Perioden seit Mittag UTC am Ursprungsdatum. Das ist normalerweise nicht das, was Sie brauchen, es sei denn, Sie leben 12 Stunden westlich von Greenwich. Wenn Sie beispielsweise in London leben, ist dieser Morgen am selben Juli wie gestern Nachmittag.
JulianSymes
2
Es funktioniert, wenn Sie DateCreatedin UTC sind. Wenn es stattdessen Ortszeit ist, müssen Sie julianday('now')in Ortszeit konvertieren . Ich konnte nirgendwo diese Informationen finden. Wenn Ihnen julianday('now') - julianday(DateCreated)dieser Beitrag mit einem in der Ortszeit gespeicherten Datum gefällt, wird Ihre Antwort durch Ihren Versatz von GMT verschoben und ist falsch. Obwohl es möglicherweise nicht empfehlenswert ist, Daten in der Ortszeit zu speichern, kann dies dennoch in Apps vorkommen, in denen Zeitzonen keine Rolle spielen (außer wenn das Tool, mit dem Sie arbeiten, sie Ihnen aufzwingt, wie hier).
Vapcguy
3
Unter der Annahme, dass DateCreated in der Ortszeit ist, julianday('now') - julianday(DateCreated, 'utc')funktioniert dies nicht auf die gleiche Weise wie bei UTC julianday('now', 'localtime') - julianday(DateCreated). Ersteres berücksichtigt keine Sommerzeit und fügt den erstellten Daten im März-November eine zusätzliche Stunde hinzu. Letzteres erklärt es tatsächlich. stackoverflow.com/questions/41007455/…
vapcguy
59

Unterschied in Tagen

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

Unterschied in Stunden

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

Unterschied in Minuten

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

Unterschied in Sekunden

Select Cast ((
    JulianDay(ToDate) - JulianDay(FromDate)
) * 24 * 60 * 60 As Integer)
Sayka
quelle
1
Für SQLite Version 3.12.0 hat der Cast-Ausdruck den AS-TYP in den Klammern. zB "Cast auswählen (5.6 As Integer);" sqlite.org/lang_expr.html#castexpr Ansonsten wirklich nützliche Beispiele.
Rob
Danke @rob. Jemand hat vorgeschlagen, mich vorher so zu bearbeiten. Aber als ich es in Sqlitebrowser versuchte, funktionierte es nicht. Vielleicht, weil es eine ältere Version ist. Also habe ich es so gehalten wie es ist ..
Sayka
Ich habe gerade SQLitebrowser verwendet und den Fehler Rob erwähnt. Darf ich Ihren Beitrag nach dem modernen Wortlaut bearbeiten?
Noumenon
@ Noumenon bitte schlagen Sie Ihre Bearbeitung vor. Ich werde es hier in sqlitebrowser überprüfen und wenn es funktioniert, werde ich Ihre Bearbeitung sicherlich genehmigen. Vielen Dank für Ihre Zeit.
Sayka
2
Diese Antwort ist weitaus umfangreicher als die akzeptierte Antwort, IMHO.
Marcus Parsons
33

Beide Antworten bieten Lösungen, die etwas komplexer sind, als sie sein müssen. Angenommen, die Zahlung wurde am erstellt January 6, 2013. Und wir wollen den Unterschied zwischen diesem Datum und heute wissen.

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

Die Differenz beträgt 34 ​​Tage. Wir können julianday('now')für eine bessere Klarheit verwenden. Mit anderen Worten, wir müssen nicht date()oder datetime()Funktionen als Parameter setzen, um zu julianday() funktionieren.

Jan Bodnar
quelle
Ich bin nicht sicher, aber wenn dieser Befehl im Code enthalten war und der Wert vom 6. Januar 2013 aus der Datenbank stammt, muss der verwendete Datentyp berücksichtigt werden.
NoChance
23

Die SQLite-Dokumentation ist eine hervorragende Referenz, und die Seite DateAndTimeFunctions eignet sich gut als Lesezeichen.

Es ist auch hilfreich, sich daran zu erinnern, dass das Spielen mit Abfragen mit dem Befehlszeilenprogramm sqlite ziemlich einfach ist:

sqlite> select julianday(datetime('now'));
2454788.09219907
sqlite> select datetime(julianday(datetime('now')));
2008-11-17 14:13:55
Konverter42
quelle
1
Da diese Seite mit einem Google-Suchmaschinen-Ranking versehen ist, hier der aktuelle Link: sqlite.org/lang_datefunc.html
markusN
9

Diese Antwort ist etwas langwierig, und die Dokumentation sagt Ihnen dies nicht (da davon ausgegangen wird, dass Sie Ihre Daten als UTC-Daten in der Datenbank speichern). Die Antwort auf diese Frage hängt jedoch weitgehend von der Zeitzone ab, in der Ihre Daten gespeichert sind in. Sie verwenden auch nicht Date('now'), aber verwenden Sie diejulianday() Funktion , um beide Daten gegen ein gemeinsames Datum zu berechnen und dann die Differenz dieser Ergebnisse voneinander zu subtrahieren.

Wenn Ihre Daten in UTC gespeichert sind:

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

Dies ist, was die hochrangige Antwort hat, und ist auch in der Dokumentation . Es ist nur ein Teil des Bildes und eine sehr vereinfachte Antwort, wenn Sie mich fragen.

Wenn Ihre Daten in der Ortszeit gespeichert sind, wird Ihre Antwort mit dem obigen Code FALSCH um die Anzahl der Stunden, die Ihr GMT-Offset beträgt. Wenn Sie wie ich in den östlichen USA sind, was GMT -5 ist, werden Ihrem Ergebnis 5 Stunden hinzugefügt. Und wenn Sie versuchen, DateCreatedsich an UTC anzupassen, weil dies julianday('now')gegen ein GMT-Datum verstößt:

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

Dies hat einen Fehler, bei dem eine Stunde für eine DateCreatedSommerzeit (März-November) hinzugefügt wird . Angenommen, "jetzt" ist an einem Tag außerhalb der Sommerzeit mittags, und Sie haben im Juni (während der Sommerzeit) mittags etwas erstellt. Ihr Ergebnis ergibt für den Stundenanteil einen Abstand von 1 Stunde anstelle von 0 Stunden. Sie müssten eine Funktion in den Code Ihrer Anwendung schreiben, die das Ergebnis anzeigt, um das Ergebnis zu ändern und eine Stunde von den Sommerzeitdaten abzuziehen. Ich habe das getan, bis mir klar wurde, dass es eine bessere Lösung für dieses Problem gibt: SQLite vs. Oracle - Berechnung von Datumsunterschieden - Stunden

Wie mir bereits mitgeteilt wurde, stimmen beide Daten, die in der Ortszeit gespeichert sind, mit der Ortszeit überein:

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

Oder 'Z'an die Ortszeit anhängen :

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

Beide scheinen die zusätzliche Stunde für DST-Daten zu kompensieren und addieren sie nicht und führen eine direkte Subtraktion durch. Daher wird das Element, das an einem DST-Tag um 12.00 Uhr erstellt wird, wenn es an einem Nicht-DST-Tag um 12.00 Uhr überprüft wird, keine zusätzliche Stunde erhalten, wenn Berechnung durchführen.

Und obwohl ich weiß, dass die meisten sagen werden, dass Datumsangaben nicht in Ortszeit in Ihrer Datenbank gespeichert werden und dass sie in UTC gespeichert werden sollen, damit Sie nicht darauf stoßen, hat nicht jede Anwendung ein weltweites Publikum und nicht jeder Programmierer möchte dies jedes Mal, wenn sie ein GET oder SET in der Datenbank ausführen, die Konvertierung JEDES Datums in ihrem System in UTC und wieder zurück zu durchlaufen und herauszufinden, ob etwas lokal oder in UTC ist.

vapcguy
quelle
"Es ist nur ein Teil des Bildes und eine sehr vereinfachte Antwort, wenn Sie mich fragen." Ja, du hast recht. Aber meine Antwort wurde 3 Minuten nachdem er seine Frage gestellt hatte gegeben, als deine zwei Jahre später kommt. Einfach, aber sie schien zu ihm zu passen.
Fred
1
@Fred Fair genug. Aber es hat mich tatsächlich mitgenommen, wie ich oben beschrieben habe, und hat mir deshalb nicht geholfen. Ich wollte sichergehen, dass jeder, der dies in Zukunft sieht, genau weiß, was los ist, damit er nicht die gleichen Fallstricke wie ich hat - oder wenn er es tut, weiß er, wie er aus ihnen herauskommt.
Vapcguy
@Fred, das ist eine sehr gute Erklärung und ich bin mir nicht sicher, was ich erwarten soll? Vielleicht posten Sie Ihre Antwort?
NoChance
Danke für Ihre Erklärung. Ich bin mir nicht sicher, ob die SQLite-Leute beschlossen haben, gegen die Standards zu verstoßen, die die Leute über Jahre hinweg akzeptiert haben, und die zu einer unnötig komplexen Implementierung geführt haben und in einem kritischen Aspekt wie Datum und Uhrzeit schwer zu testen sind! Stellen Sie sich vor, wie viele Testfälle erforderlich sind, um zu überprüfen, ob jedes Datum in der Anwendung so funktioniert, wie es der Mensch erwartet!
NoChance
3

Nur eine Notiz zum Schreiben von Zeitschaltuhrfunktionen. Für diejenigen, die nach geleisteten Arbeitsstunden suchen, werden bei einer sehr einfachen Änderung die Stunden plus die Minuten als Prozentsatz von 60 angezeigt, wie es die meisten Lohn- und Gehaltsabrechnungsunternehmen wünschen.

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
quelle
Trotzdem eine
nette
3

Wenn Sie Zeit im 00:00-Format haben möchten: Ich habe es so gelöst:

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

Wenn Ihr Datumsformat wie folgt lautet: "JJJJ-MM-TT HH: MM: SS", wenn Sie den Unterschied zwischen zwei Daten in der Anzahl der Monate ermitteln müssen:

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

Ashish Koshy
quelle
2

Erstens ist nicht klar, wie Ihr Datumsformat lautet. Es gibt bereits eine Antwort mitstrftime("%s") .

Ich möchte diese Antwort erweitern.

SQLite hat nur die folgenden Speicherklassen: NULL, INTEGER, REAL, TEXT oder BLOB. Zur Vereinfachung gehe ich davon aus, dass die Daten REAL sind und die Sekunden seit dem 01.01.1970 enthalten. Hier ist ein Beispielschema, für das ich die Beispieldaten vom "1. Dezember 2018" einfügen werde:

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

Lassen Sie uns nun den Datumsunterschied zwischen "1. Dezember 2018" und jetzt herausarbeiten (während ich dies schreibe, ist es Mittag, 12. Dezember 2018):

Datumsunterschied in Tagen:

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

Datumsunterschied in Stunden:

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

Datumsunterschied in Minuten:

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

Datumsunterschied in Sekunden:

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

Wenn Sie einen Unterschied in Sekunden wollen

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

Wenn Sie Aufzeichnungen zwischen Tagen wünschen,

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

In meinem Fall muss ich die Differenz in Minuten berechnen und julianday()gebe keinen genauen Wert an. Stattdessen benutze ich strftime():

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

Beide Daten werden in Unixtime (Sekunden) konvertiert und dann subtrahiert, um den Wert in Sekunden zwischen den beiden Daten zu erhalten. Teilen Sie es als nächstes durch 60.

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

Yusril Maulidan Raji
quelle