O SQLite não tem um tipo de data de verdade
Isso pega de surpresa quem vem do Postgres ou do MySQL. O SQLite tem apenas cinco classes de armazenamento — NULL, INTEGER, REAL, TEXT e BLOB. Não existe DATE, nem DATETIME, nem TIMESTAMP. Você pode até escrever created_at DATETIME no seu CREATE TABLE, e o SQLite aceita numa boa, mas o valor vai ser guardado como texto puro ou número.
O que o SQLite oferece é um conjunto de funções de data e hora que entendem três formatos convencionais:
- Texto no formato ISO 8601 —
'2026-04-23','2026-04-23 10:15:00','2026-04-23T10:15:00.123Z'. - Timestamp Unix — segundos desde 1970-01-01 UTC, armazenado como inteiro.
- Dia juliano (Julian day) — dias fracionários desde 4714 a.C., armazenado como real.
Escolha um e mantenha o padrão. O texto ISO 8601 é o mais legível e ordena corretamente como string, e é justamente por isso que ele é o formato padrão.
Quatro formas de pedir o "agora" — data em texto, data e hora em texto, segundos Unix e dia Juliano. Todas representam o mesmo instante.
As cinco funções de data e hora no SQLite
O SQLite traz cinco funções nativas que cobrem praticamente tudo o que você vai precisar no dia a dia:
date(time, ...)— devolveYYYY-MM-DD.time(time, ...)— devolveHH:MM:SS.datetime(time, ...)— devolveYYYY-MM-DD HH:MM:SS.julianday(time, ...)— devolve um número real (ótimo para calcular diferenças entre datas).strftime(format, time, ...)— devolve uma string com o formato que você quiser.
Todas recebem um valor de tempo como primeiro argumento e, depois disso, quantos modificadores você quiser passar.
Repare no 'unixepoch' — é assim que você avisa às funções de data que o número inteiro de entrada é um timestamp Unix, e não um dia juliano. Sem ele, o SQLite assume que o número é juliano.
strftime: formatos de data personalizados no SQLite
A função strftime é o coringa para formatar datas. Os mesmos códigos % que você já conhece do C ou do Python:
Os códigos que você vai usar com mais frequência:
%Y— ano com quatro dígitos.%m— mês (01-12).%d— dia do mês (01-31).%H,%M,%S— horas, minutos, segundos.%w— dia da semana (0=domingo).%j— dia do ano (001-366).%s— timestamp Unix.%f— segundos fracionários (SS.SSS).
O strftime também é como você extrai partes de uma data — não existe uma função EXTRACT ou YEAR() separada no SQLite. Você simplesmente formata até a parte que quer e converte para número, se precisar:
strftime sempre devolve texto, então embrulhe a chamada em CAST(... AS INTEGER) quando precisar fazer contas ou comparações numéricas.
Modificadores: aritmética de datas sem operadores
Esse é o recurso que torna o trabalho com datas no SQLite realmente agradável. Depois do argumento de tempo, você pode passar quantas strings de modificador quiser, e elas são aplicadas na ordem em que aparecem:
Os modificadores que você vai usar o tempo todo:
'+N days','-N days', e o mesmo parahours,minutes,seconds,months,years.'start of day','start of month','start of year'— trunca a data até aquele ponto.'weekday N'— avança até o próximo dia da semana indicado (0=domingo).'localtime'e'utc'— convertem entre fusos horários.
Aquele truque do "último dia do mês" — start of month, mais um mês, menos um dia — vale a pena decorar. O SQLite não tem função LAST_DAY, mas encadeando modificadores você chega no mesmo resultado.
UTC vs. horário local no SQLite
O 'now' sempre devolve em UTC. Se você quer o horário local (tipo converter UTC para horário de Brasília), precisa pedir explicitamente:
O modificador 'localtime' pega um valor em UTC e converte para o fuso do sistema. Já o 'utc' faz o caminho inverso: assume que a entrada está no horário local e converte para UTC.
A regra de ouro: armazene tudo em UTC e só converta para o horário local na hora de exibir. Misturar fusos no banco gera bugs chatos, daqueles que só aparecem duas vezes por ano, quando o horário de verão entra ou sai.
Comparando datas e filtrando intervalos no SQLite
Se você guardar as datas como texto no formato ISO 8601, comparações e BETWEEN funcionam de cara — a ordem lexicográfica do ISO 8601 é a mesma da ordem cronológica. É justamente por isso que ele é o formato padrão.
O intervalo semiaberto (>= start, < end) é um hábito que vale a pena adotar — ele elimina de vez aquela dúvida do tipo "será que a meia-noite do dia 30 entrou ou não?".
Para pegar "os últimos 7 dias", deixe o próprio SQLite calcular o limite:
Diferença entre datas no SQLite
O SQLite não tem uma função DATEDIFF como outros bancos. Mas não se preocupe: dois padrões resolvem praticamente todos os casos:
As diferenças retornadas por julianday() vêm em dias (com precisão fracionária). Então, se você multiplicar por 24, tem horas; por 1440, tem minutos. Já as diferenças com strftime('%s', ...) vêm em segundos — bem prático quando o que você quer é um inteiro.
Para contar apenas dias inteiros, use CAST(... AS INTEGER), que descarta a parte fracionária:
Como armazenar datas no SQLite: escolha um formato e mantenha
Você tem três opções razoáveis, na ordem em que deveria escolher:
- Texto ISO 8601 (
TEXT). É legível em dumps, ordena corretamente e funciona bem com todas as funções de data. É a escolha padrão. - Segundos Unix (
INTEGER). Compacto, comparações rápidas, sem ambiguidade de fuso horário. Vale a pena quando você tem milhões de linhas. Para ler de volta, vai precisar dedatetime(col, 'unixepoch'). - Dia juliano (
REAL). Raramente compensa, a não ser que você faça muita aritmética de datas e queira precisão de subsegundos numa única coluna.
O que você não deve fazer é misturar formatos na mesma coluna. As funções de data aceitam qualquer um sem reclamar, mas índices, ordenações e comparações vão devolver resultados sem sentido.
DEFAULT (datetime('now')) é o equivalente no SQLite ao DEFAULT CURRENT_TIMESTAMP — ele carimba cada linha nova com o horário UTC atual, sem precisar de nenhuma linha de código na aplicação.
Agrupando por período de tempo
A função strftime brilha quando você quer agrupar registros por mês, semana ou hora:
A mesma ideia vale para "pedidos por hora do dia", "cadastros por dia da semana" ou "eventos por minuto" — escolha uma string de formato que capture apenas a granularidade desejada, agrupe por ela e agregue.
A seguir: funções de agregação
Por falar em agrupar, esse COUNT(*) é a mais simples das funções de agregação do SQLite. No próximo tópico vamos ver o conjunto completo: SUM, AVG, MIN, MAX e como elas condensam várias linhas em um único valor de resumo.
Perguntas frequentes
O SQLite tem um tipo DATE ou DATETIME?
Não — o SQLite não tem um tipo de data dedicado. Você guarda datas como TEXT no formato ISO 8601 ('2026-04-23 10:15:00'), como timestamp Unix em INTEGER, ou como dia juliano em REAL. As funções de data nativas aceitam os três formatos e, por padrão, devolvem texto ISO 8601.
Como pegar a data e hora atual no SQLite?
Use date('now') para a data atual, time('now') para a hora, datetime('now') para os dois e strftime('%s', 'now') para um timestamp Unix. Por padrão tudo isso vem em UTC — passe o modificador 'localtime' para converter: datetime('now', 'localtime').
Como somar dias ou meses a uma data no SQLite?
Basta passar uma string modificadora para qualquer função de data: date('2026-04-23', '+7 days'), date('now', '-1 month'), datetime('now', '+2 hours', '+30 minutes'). Os modificadores são aplicados na ordem em que aparecem, e as unidades incluem days, hours, minutes, seconds, months e years.
Como calcular a diferença entre duas datas?
Para dias, use julianday(end) - julianday(start) — como o dia juliano é ponto flutuante, o resultado já inclui a fração do dia. Para segundos, subtraia os timestamps Unix: strftime('%s', end) - strftime('%s', start). O SQLite não tem DATEDIFF, mas esses dois padrões resolvem praticamente todos os casos.