Diferença entre 2 datas no SQLite

110

Como faço para obter a diferença em dias entre 2 datas no SQLite? Já tentei algo assim:

SELECT Date('now') - DateCreated FROM Payment

Ele retorna 0 todas as vezes.

Agustín Meriles
fonte

Respostas:

123
 SELECT julianday('now') - julianday(DateCreated) FROM Payment;
Fred
fonte
10
Observe que, apesar do que o nome da função pode fazer pensar, ela tem uma granularidade maior do que dias. É um número de dias, mas pode ser fracionário.
lindes
10
Lembre-se de que julianday retorna o número (fracionário) de 'dias' - ou seja, períodos de 24 horas, a partir do meio-dia UTC da data de origem. Geralmente não é disso que você precisa, a menos que viva 12 horas a oeste de Greenwich. Por exemplo, se você mora em Londres, esta manhã é no mesmo dia de julho da tarde de ontem.
JulianSymes
2
Funciona se você DateCreatedestiver em UTC. Se, em vez disso, for a hora local, você deve converter julianday('now')para a hora local. Não consegui encontrar em nenhum lugar que tivesse essa informação. Se você julianday('now') - julianday(DateCreated)gostar desta postagem sugerir com uma data armazenada no horário local, sua resposta estará errada por seu deslocamento do GMT e estará errada. Embora talvez não seja uma prática recomendada armazenar datas no horário local, isso ainda pode acontecer em aplicativos onde os fusos horários não importam (exceto quando a ferramenta com a qual você está trabalhando os impõe, como aqui).
vapcguy
3
Supondo que DateCreated esteja no horário local, se você fizer isso julianday('now') - julianday(DateCreated, 'utc'), para fazer ambos UTC, não funcionará da mesma maneira que fazer julianday('now', 'localtime') - julianday(DateCreated). O primeiro não leva em conta os dias do horário de verão e adicionará uma hora extra às datas criadas em março-novembro. O último realmente explica isso. stackoverflow.com/questions/41007455/…
vapcguy
59

Diferença em dias

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

Diferença em horas

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

Diferença em minutos

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

Diferença em segundos

Select Cast ((
    JulianDay(ToDate) - JulianDay(FromDate)
) * 24 * 60 * 60 As Integer)
Sayka
fonte
1
para sqlite versão 3.12.0, a expressão cast tem AS TYPE entre colchetes. por exemplo, "Selecionar Cast (5.6 As Integer);" sqlite.org/lang_expr.html#castexpr Caso contrário, exemplos realmente úteis.
roubar
Obrigado @rob. Alguém propôs me editar assim antes. Mas quando tentei no Sqlitebrowser, não estava funcionando. Talvez por ser uma versão mais antiga. Então eu mantive como está ..
Sayka
Acabei de usar o SQLitebrowser e o erro rob foi mencionado. Posso editar sua postagem para o texto moderno?
Noumenon,
@Noumenon, por favor, proponha sua edição. Vou verificar no sqlitebrowser aqui e se funcionar, com certeza aprovarei sua edição. Obrigado pelo seu tempo.
Sayka
2
Esta resposta é muito mais preenchida com recursos do que a resposta aceita, IMHO.
Marcus Parsons
33

Ambas as respostas fornecem soluções um pouco mais complexas, como precisam ser. Digamos que o pagamento foi criado em January 6, 2013. E queremos saber a diferença entre esta data e hoje.

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

A diferença é de 34 dias. Podemos usar julianday('now')para maior clareza. Em outras palavras, não precisamos colocar date()ou datetime()funções como parâmetros para julianday() funcionar.

Jan Bodnar
fonte
Não tenho certeza, mas se este comando estava em código e o valor 6 de janeiro de 2013 veio do banco de dados, é necessário considerar o tipo de dados usado.
NoChance,
23

A documentação do SQLite é uma ótima referência e a página DateAndTimeFunctions é uma boa para marcar.

Também é útil lembrar que é muito fácil brincar com as consultas com o utilitário de linha de comando sqlite:

sqlite> select julianday(datetime('now'));
2454788.09219907
sqlite> select datetime(julianday(datetime('now')));
2008-11-17 14:13:55
conversor 42
fonte
1
Como esta página vem com uma classificação do mecanismo de pesquisa do Google, aqui está o link atual: sqlite.org/lang_datefunc.html
markusN
9

Esta resposta é um pouco prolixa e a documentação não dirá isso (porque eles assumem que você está armazenando suas datas como datas UTC no banco de dados), mas a resposta a esta pergunta depende muito do fuso horário em que suas datas estão armazenadas in. Você também não usa Date('now'), mas usa a julianday()função, para calcular ambas as datas em relação a uma data comum e, em seguida, subtrair a diferença desses resultados entre si.

Se suas datas estiverem armazenadas em UTC:

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

Isso é o que a resposta com melhor classificação tem, e também está na documentação . É apenas parte da imagem e uma resposta muito simplista, se você me perguntar.

Se suas datas forem armazenadas no horário local, usar o código acima tornará sua resposta ERRADA pelo número de horas em que seu deslocamento GMT está. Se você estiver no leste dos EUA como eu, que é GMT -5, seu resultado terá 5 horas adicionadas. E se você tentar se DateCreatedconformar com UTC porque julianday('now')vai contra uma data GMT:

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

Isso tem um bug que adiciona uma hora para um DateCreatedque é durante o horário de verão (março-novembro). Digamos que "agora" seja ao meio-dia em um dia diferente do horário de verão e você criou algo em junho (durante o horário de verão) ao meio-dia, seu resultado dará 1 hora de intervalo, em vez de 0 horas, para a parte das horas. Você teria que escrever uma função no código do seu aplicativo que está exibindo o resultado para modificar o resultado e subtrair uma hora das datas do horário de verão. Fiz isso, até perceber que havia uma solução melhor para aquele problema que estava tendo: SQLite vs. Oracle - Calculando diferenças de data - horas

Em vez disso, como foi apontado para mim, para datas armazenadas na hora local, faça com que ambas correspondam à hora local:

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

Ou acrescente 'Z'a hora local:

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

Ambos parecem compensar e não adicionar a hora extra para datas de horário de verão e fazer subtração direta - de modo que o item criado ao meio-dia em um dia de horário de verão, ao verificar ao meio-dia em um dia não horário de verão, não receberá uma hora extra quando realizar o cálculo.

E embora eu reconheça que a maioria dirá não armazene datas no horário local em seu banco de dados e armazene-as em UTC para que você não se depare com isso, bem, nem todo aplicativo tem um público mundial, e nem todo programador deseja para passar pela conversão de CADA data em seu sistema para UTC e vice-versa toda vez que eles fizerem um GET ou SET no banco de dados e tentar descobrir se algo é local ou em UTC.

vapcguy
fonte
"É apenas parte da imagem e uma resposta muito simplista, se você me perguntar." Sim você está certo. Mas minha resposta foi dada três minutos depois que ele fez sua pergunta, quando a sua veio dois anos depois. Simplista, mas ela parecia combinar com ele.
Fred
1
@Fred Muito justo. Mas na verdade acabou me levando para um passeio, como descrevi acima, e por isso não me ajudou. Eu queria ter certeza de que qualquer pessoa que visse isso no futuro sabia exatamente o que estava acontecendo, para que não caísse nas mesmas armadilhas que eu - ou, se acontecesse, saberia como sair delas.
vapcguy
@Fred, esta é uma explicação muito boa e não tenho certeza do que esperava? Talvez poste sua resposta?
NoChance de
Obrigado pela sua explicação. Não tenho certeza se o pessoal do SQLite decidiu ir contra os padrões que as pessoas passaram a aceitar ao longo dos anos e acabaram com uma implementação desnecessariamente complexa e difícil de testar em um aspecto crítico como data e hora! Imagine o número de casos de teste necessários para verificar se cada data no aplicativo funciona como os humanos esperam!
NoChance de
3

Apenas uma nota para escrever funções de relógio. Para quem procura horas trabalhadas, uma alteração muito simples disso faz com que as horas mais os minutos sejam mostrados como uma porcentagem de 60, conforme a maioria das empresas de folha de pagamento deseja.

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
fonte
No entanto, uma pequena consulta
legal
3

Se você quiser o horário no formato 00:00: Resolvi assim:

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

Dado que o seu formato de data segue: "AAAA-MM-DD HH: MM: SS", se você precisar encontrar a diferença entre duas datas em número de meses:

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

Ashish Koshy
fonte
2

Em primeiro lugar, não está claro qual é o seu formato de data. Já existe uma resposta envolvendo strftime("%s").

Eu gosto de expandir essa resposta.

O SQLite possui apenas as seguintes classes de armazenamento: NULL, INTEGER, REAL, TEXT ou BLOB. Para simplificar, vou assumir que as datas são REAIS contendo os segundos desde 01/01/1970. Aqui está um esquema de amostra para o qual colocarei os dados de amostra de "1º de dezembro de 2018":

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

Agora vamos calcular a diferença de data entre "1º de dezembro de 2018" e agora (enquanto escrevo isso, é meio-dia de 12 de dezembro de 2018):

Diferença de data em dias:

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

Diferença de data em horas:

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

Diferença de data em minutos:

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

Diferença de data em segundos:

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

Se você quiser diferença em segundos

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

Se você quiser registros entre dias,

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

No meu caso, tenho que calcular a diferença em minutos e julianday()não dou um valor preciso. Em vez disso, eu uso strftime():

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

Ambas as datas são convertidas em unixtime (segundos) e, em seguida, subtraídas para obter o valor em segundos entre as duas datas. Em seguida, divida por 60.

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

Yusril Maulidan Raji
fonte