Diferencia entre 2 fechas en SQLite

110

¿Cómo obtengo la diferencia en días entre 2 fechas en SQLite? Ya probé algo como esto:

SELECT Date('now') - DateCreated FROM Payment

Devuelve 0 cada vez.

Agustín Meriles
fuente

Respuestas:

123
 SELECT julianday('now') - julianday(DateCreated) FROM Payment;
Fred
fuente
10
Tenga en cuenta que a pesar de lo que pueda hacer pensar el nombre de la función, esta tiene una granularidad mayor que los días. Son varios días, pero pueden ser fraccionarios.
lindes
10
Tenga en cuenta que julianday devuelve el número (fraccional) de 'días', es decir, períodos de 24 horas, desde el mediodía UTC en la fecha de origen. Por lo general, eso no es lo que necesita, a menos que viva 12 horas al oeste de Greenwich. Por ejemplo, si vive en Londres, esta mañana es el mismo día de julio que ayer por la tarde.
JulianSymes
2
Funciona si DateCreatedestá en UTC. Si, en cambio, es la hora local, debe convertir julianday('now')a la hora local. No pude encontrar ningún lugar que tuviera esta información. Si le julianday('now') - julianday(DateCreated)gusta que esta publicación sugiera con una fecha almacenada en la hora local, su respuesta estará fuera de su compensación de GMT y será incorrecta. Si bien tal vez no sea la mejor práctica para almacenar fechas en la hora local, aún puede suceder en aplicaciones donde las zonas horarias no importan (excepto cuando la herramienta con la que está trabajando las obliga a usted, como aquí).
vapcguy
3
Suponiendo que DateCreated está en la hora local, si lo hace julianday('now') - julianday(DateCreated, 'utc'), para hacer ambas UTC, no funciona de la misma manera julianday('now', 'localtime') - julianday(DateCreated). El primero no tiene en cuenta los días de horario de verano y agregará una hora adicional a las fechas creadas en marzo-noviembre. Este último realmente lo explica. stackoverflow.com/questions/41007455/…
vapcguy
60

Diferencia en días

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

Diferencia en horas

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

Diferencia en minutos

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

Diferencia en segundos

Select Cast ((
    JulianDay(ToDate) - JulianDay(FromDate)
) * 24 * 60 * 60 As Integer)
Sayka
fuente
1
para la versión 3.12.0 de sqlite, la expresión de conversión tiene AS TYPE entre corchetes. por ejemplo, "Seleccionar Cast (5.6 como entero)"; sqlite.org/lang_expr.html#castexpr Por lo demás, ejemplos realmente útiles.
robo el
Gracias @rob. Alguien propuso editarme así antes. Pero cuando lo probé en Sqlitebrowser, no estaba funcionando. Tal vez sea por ser una versión anterior. Así que lo mantuve como está ..
Sayka
Acabo de usar SQLitebrowser y mencioné el error rob .. ¿Puedo editar tu publicación con la redacción moderna?
Noumenon
@Noumenon por favor proponga su edición. Lo comprobaré en sqlitebrowser aquí y, si funciona, seguramente aprobaré su edición. Gracias por tu tiempo.
Sayka
2
Esta respuesta tiene muchas más funciones que la respuesta aceptada, en mi humilde opinión.
Marcus Parsons
33

Ambas respuestas brindan soluciones un poco más complejas, como deben ser. Digamos que el pago se creó el January 6, 2013. Y queremos saber la diferencia entre esta fecha y la de hoy.

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

La diferencia es de 34 días. Podemos utilizar julianday('now')para una mayor claridad. En otras palabras, no necesitamos poner date()o datetime()funciones como parámetros para julianday() funcionar.

Jan Bodnar
fuente
No estoy seguro, pero si este comando estaba en código, y el valor del 6 de enero de 2013 proviene de la base de datos, es necesario considerar el tipo de datos utilizado.
NoChance
23

La documentación de SQLite es una gran referencia y las funciones DateAndTimeFunctions página es una buena para marcar.

También es útil recordar que es bastante fácil jugar con consultas con la utilidad de línea de comando sqlite:

sqlite> select julianday(datetime('now'));
2454788.09219907
sqlite> select datetime(julianday(datetime('now')));
2008-11-17 14:13:55
convertidor42
fuente
1
Dado que esta página viene con un ranking de motor de búsqueda de Google, aquí el enlace actual: sqlite.org/lang_datefunc.html
markusN
9

Esta respuesta es un poco larga y la documentación no le dirá esto (porque asumen que está almacenando sus fechas como fechas UTC en la base de datos), pero la respuesta a esta pregunta depende en gran medida de la zona horaria en la que se almacenan sus fechas. en. Tampoco usa Date('now'), pero usa eljulianday() función, para calcular ambas fechas contra una fecha común, luego reste la diferencia de esos resultados entre sí.

Si sus fechas están almacenadas en UTC:

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

Esto es lo que tiene la respuesta mejor clasificada, y también está en la documentación . Es solo una parte de la imagen y una respuesta muy simplista, si me preguntas.

Si sus fechas están almacenadas en la hora local, el uso del código anterior hará que su respuesta sea INCORRECTA según el número de horas de su compensación GMT. Si se encuentra en el este de los EE. UU. Como yo, que es GMT -5, su resultado tendrá 5 horas agregadas. Y si intenta DateCreatedcumplir con UTC porque julianday('now')va en contra de una fecha GMT:

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

Esto tiene un error en el que agregará una hora DateCreateddurante el horario de verano (marzo-noviembre). Digamos que "ahora" es al mediodía en un día sin horario de verano y que creó algo en junio (durante el horario de verano) al mediodía, su resultado dará 1 hora de diferencia, en lugar de 0 horas, para la porción de horas. Tendría que escribir una función en el código de su aplicación que muestre el resultado para modificar el resultado y restar una hora de las fechas del horario de verano. Hice eso, hasta que me di cuenta de que hay una mejor solución para ese problema que estaba teniendo: SQLite vs.Oracle - Cálculo de diferencias de fecha - horas

En cambio, como se me señaló, para las fechas almacenadas en la hora local, haga que ambas coincidan con la hora local:

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

O agregar 'Z'a la hora local:

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

Ambos parecen compensar y no suman la hora extra para las fechas de horario de verano y hacen una resta directa, de modo que el artículo creado al mediodía en un día de horario de verano, al verificar al mediodía en un día que no es de horario de verano, no obtendrá una hora extra cuando realizar el cálculo.

Y aunque reconozco que la mayoría dirá que no almacene las fechas en la hora local en su base de datos y que las almacene en UTC para que no se encuentre con esto, bueno, no todas las aplicaciones tienen una audiencia mundial, y no todos los programadores quieren para pasar por la conversión de CADA fecha en su sistema a UTC y viceversa cada vez que hacen un GET o SET en la base de datos y tratan de averiguar si algo es local o en UTC.

vapcguy
fuente
"Es sólo una parte de la imagen, y una respuesta muy simplista, si me preguntas". Si, tienes razón. Pero mi respuesta fue dada 3 minutos después de que él hizo su pregunta cuando la tuya llega dos años después. Simplista, pero parecía encajar con él.
Fred
1
@Fred Bastante justo. Pero en realidad terminó llevándome a dar una vuelta, como describí anteriormente, por lo que no me ayudó. Quería estar seguro de que cualquiera que viera esto en el futuro supiera exactamente lo que estaba sucediendo para que no tuvieran los mismos escollos que yo, o, si lo hicieran, sabrían cómo salir de ellos.
vapcguy
@Fred, esta es una muy buena explicación y no estoy seguro de qué esperar. ¿Quizás publique su respuesta?
NoChance
Gracias por tu explicación. No estoy seguro de que la gente de SQLite haya decidido ir en contra de los estándares que la gente ha llegado a aceptar durante años y terminó con una implementación innecesariamente compleja y difícil de probar en un aspecto crítico como la fecha y la hora. ¡Imagínese la cantidad de casos de prueba necesarios para verificar que cada fecha en la aplicación funcione como los humanos esperan!
NoChance
3

Solo una nota para escribir funciones de reloj temporizador. Para aquellos que buscan horas trabajadas, un cambio muy simple de esto hace que las horas más los minutos se muestren como un porcentaje de 60 como la mayoría de las empresas de nómina lo desean.

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
fuente
Sin embargo, una pequeña consulta
ordenada
3

Si quieres tiempo en formato 00:00: Lo resolví así:

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

Dado que su formato de fecha es el siguiente: "AAAA-MM-DD HH: MM: SS", si necesita encontrar la diferencia entre dos fechas en el número de meses:

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

Ashish Koshy
fuente
2

En primer lugar, no está claro cuál es su formato de fecha. Ya hay una respuesta que involucrastrftime("%s") .

Me gusta ampliar esa respuesta.

SQLite solo tiene las siguientes clases de almacenamiento: NULL, INTEGER, REAL, TEXT o BLOB. Para simplificar las cosas, voy a asumir que las fechas son REALES y contienen los segundos desde 1970-01-01. Aquí hay un esquema de muestra para el que incluiré los datos de muestra del "1 de diciembre de 2018":

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

Ahora calculemos la diferencia de fecha entre el "1 de diciembre de 2018" y ahora (mientras escribo esto, es el mediodía del 12 de diciembre de 2018):

Diferencia de fecha en días:

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

Diferencia de fecha en horas:

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

Diferencia de fecha en minutos:

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

Diferencia de fecha en segundos:

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

Si quieres diferencia en segundos

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

Si desea registros entre días,

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

En mi caso, tengo que calcular la diferencia en minutos y julianday()no doy un valor exacto. En su lugar, uso strftime():

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

Ambas fechas se convierten a tiempo único (segundos), luego se restan para obtener un valor en segundos entre las dos fechas. Luego, divídelo entre 60.

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

Yusril Maulidan Raji
fuente