Menu

Datas e Horas no SQLite: strftime, date() e datetime()

Como o SQLite armazena e manipula datas — as cinco funções de data, formatos, modificadores e as escolhas de armazenamento que mantêm suas queries rápidas.

Esta página tem editores executáveis — edite, execute e veja a saída na hora.

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, ...) — devolve YYYY-MM-DD.
  • time(time, ...) — devolve HH:MM:SS.
  • datetime(time, ...) — devolve YYYY-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 para hours, 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:

  1. Texto ISO 8601 (TEXT). É legível em dumps, ordena corretamente e funciona bem com todas as funções de data. É a escolha padrão.
  2. 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 de datetime(col, 'unixepoch').
  3. 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.

Coddy programming languages illustration

Aprenda a programar com o Coddy

COMEÇAR