SQL Funções de Data e Hora
O SQLite não tem um tipo especial para datas: ele guarda a data como texto no formato AAAA-MM-DD (como os pedidos da Loja Aurora: '2026-10-14') e oferece funções para ler, calcular e formatar esse texto. Esta página reúne todas elas, com os modificadores e os códigos do strftime, cada um com o resultado real. A explicação passo a passo está nas aulas Datas e Horas e Funções de Data.
- Exemplo vai dentro de um
SELECT:SELECT date('2026-10-14', '+1 day');. - Resultado foi colhido no editor do guia (SQLite 3.50.4). Os exemplos usam datas fixas, porque
'now'("agora") muda a cada segundo. - As funções trabalham em UTC (o horário de Greenwich, 3 horas à frente de Brasília), a não ser que você peça
'localtime'. - Se a data ou um modificador estiver errado, o resultado é NULL, sem mensagem de erro.
As funções
Todas recebem um valor de tempo (uma data, uma data com hora, ou 'now') e, depois dele, zero ou mais modificadores (tabela Modificadores).
| Função | Devolve | Exemplo | Resultado | Aula |
|---|---|---|---|---|
date(t, …) | A data: AAAA-MM-DD. | date('2026-10-14 15:30:45') | 2026-10-14 | Funções de Data |
time(t, …) | A hora: HH:MM:SS. | time('2026-10-14 15:30:45') | 15:30:45 | |
datetime(t, …) | Data e hora: AAAA-MM-DD HH:MM:SS. | datetime('2026-10-14') | 2026-10-14 00:00:00 | |
julianday(t, …) | O dia juliano: quantos dias (com fração) se passaram desde o meio-dia de 24/11/4714 a.C. Serve para fazer contas de dias. | julianday('2026-10-14') | 2461327.5 | Datas e Horas |
unixepoch(t, …) | Segundos desde 01/01/1970 00:00 UTC (o "tempo Unix", muito usado em programas). | unixepoch('2026-10-14') | 1791936000 | |
strftime(formato, t, …) | A data escrita do jeito que você quiser (tabela strftime). | strftime('%d/%m/%Y', '2026-10-14') | 14/10/2026 | Funções de Data |
timediff(a, b) | A diferença a - b, em anos, meses, dias e horas (para gente ler, não para contas). | timediff('2026-10-14 15:30', '2024-01-05 08:00') | +0002-09-09 07:30:00.000 | |
Com b depois de a, o sinal fica negativo | timediff('2026-10-05', '2026-10-14') | -0000-00-09 00:00:00.000 | ||
CURRENT_DATE | A data de hoje (UTC), sem parênteses. | length(CURRENT_DATE) | 10 (muda todo dia) | DEFAULT |
CURRENT_TIME | A hora agora (UTC). | length(CURRENT_TIME) | 8 | |
CURRENT_TIMESTAMP | Data e hora agora (UTC). Muito usado em DEFAULT CURRENT_TIMESTAMP. | length(CURRENT_TIMESTAMP) | 19 | DEFAULT |
No terminal da Ana, com o relógio de verdade. Repare que 'now' e CURRENT_TIMESTAMP estão em UTC, e só o 'localtime' mostra a hora do relógio dela (Brasília, 3 horas a menos):
sqlite> SELECT date('now'), datetime('now'), datetime('now', 'localtime');
2026-10-18|2026-10-18 13:43:19|2026-10-18 10:43:19
sqlite> SELECT CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP;
2026-10-18|13:43:19|2026-10-18 13:43:19
Os formatos de data que o SQLite entende
| Formato | Exemplo | Resultado de datetime(…) |
|---|---|---|
AAAA-MM-DD | datetime('2026-10-14') | 2026-10-14 00:00:00 |
AAAA-MM-DD HH:MM (ou :SS, :SS.SSS) | datetime('2026-10-14 15:30') | 2026-10-14 15:30:00 |
com T no lugar do espaço | datetime('2026-10-14T15:30') | 2026-10-14 15:30:00 |
| só a hora (o dia vira 2000-01-01) | time('15:30') | 15:30:00 |
com fuso no fim (-03:00, Z): o SQLite converte para UTC | datetime('2026-10-14 15:30-03:00') | 2026-10-14 18:30:00 |
| um número (dia juliano) | date(2461327.5) | 2026-10-14 |
um número (tempo Unix), com 'unixepoch' ou 'auto' | datetime(1791936000, 'unixepoch') | 2026-10-14 00:00:00 |
'now' | date('now') | a data de hoje |
| Escrito assim | Resultado | Por quê |
|---|---|---|
date('14/10/2026') | NULL | O SQLite só entende AAAA-MM-DD. |
date('2026-2-5') | NULL | Mês e dia precisam de 2 algarismos: '2026-02-05'. |
date('2026-02-30') | 2026-03-02 | Dia que não existe "transborda" para o mês seguinte, sem aviso. |
'2026-10-14' < '2026-9-30' | 1 (verdadeiro!) | Datas são comparadas como texto, letra a letra: '1' vem antes de '9'. Com os zeros ('2026-09-30'), a comparação sai certa. |
Guarde sempre no formato AAAA-MM-DD, com zeros, e converta para DD/MM/AAAA só na hora de mostrar, com strftime('%d/%m/%Y', …).
Modificadores
Os modificadores vêm depois da data, cada um entre aspas, e são aplicados da esquerda para a direita. Os nomes são em inglês e com letras minúsculas.
| Modificador | O que faz | Exemplo | Resultado |
|---|---|---|---|
'+N days' | Soma (ou, com -, subtrai) N dias. | date('2026-10-14', '+7 days') | 2026-10-21 |
'+N hours' | Horas. | datetime('2026-10-14 15:30', '+2 hours') | 2026-10-14 17:30:00 |
'+N minutes' | Minutos. | datetime('2026-10-14 15:30', '+90 minutes') | 2026-10-14 17:00:00 |
'+N seconds' | Segundos. | datetime('2026-10-14 15:30', '-30 seconds') | 2026-10-14 15:29:30 |
'+N months' | Meses. | date('2026-10-14', '-1 month') | 2026-09-14 |
'+N years' | Anos. | date('2026-10-14', '+1 year') | 2027-10-14 |
'+HH:MM' | Soma horas e minutos de uma vez (também :SS). | datetime('2026-10-14', '+03:30') | 2026-10-14 03:30:00 |
'+AAAA-MM-DD' | Soma anos, meses e dias de uma vez. | datetime('2026-10-14', '+0001-02-03') | 2027-12-17 00:00:00 |
'start of month' | Volta para o dia 1 do mês. | date('2026-10-14', 'start of month') | 2026-10-01 |
'start of year' | Volta para 1º de janeiro. | date('2026-10-14', 'start of year') | 2026-01-01 |
'start of day' | Volta para 00:00:00 do dia. | datetime('2026-10-14 15:30', 'start of day') | 2026-10-14 00:00:00 |
'weekday N' | Avança até o próximo dia da semana N (0 = domingo, 1 = segunda… 6 = sábado). Se a data já for esse dia, fica nela. | date('2026-10-14', 'weekday 0') | 2026-10-18 (o domingo seguinte) |
'unixepoch' | Lê o número como tempo Unix (segundos desde 1970). | datetime(1791936000, 'unixepoch') | 2026-10-14 00:00:00 |
'julianday' | Lê o número como dia juliano. | date(2461327.5, 'julianday') | 2026-10-14 |
'auto' | Adivinha se o número é dia juliano ou tempo Unix. | datetime(1791936000, 'auto') | 2026-10-14 00:00:00 |
'localtime' | Converte de UTC para o fuso do computador. | datetime('2026-10-14 15:30', 'localtime') | no terminal da Ana (Brasília): 2026-10-14 12:30:00 |
'utc' | Converte do fuso do computador para UTC. | datetime('2026-10-14 12:30', 'utc') | no terminal da Ana: 2026-10-14 15:30:00 |
'subsec' ou 'subsecond' | Mostra também os milissegundos. | datetime('2026-10-14 15:30:45.123', 'subsec') | 2026-10-14 15:30:45.123 |
'ceiling' / 'floor' | Resolve datas que "não existem" depois de somar meses ou anos (como 31/01 + 1 mês). 'ceiling' (o padrão) transborda para o mês seguinte; 'floor' fica no último dia do mês. | date('2026-01-31', '+1 month')date('2026-01-31', '+1 month', 'floor') | 2026-03-032026-02-28 |
| (errado) | Um modificador que não existe (ou em português) dá NULL. | date('2026-10-14', '+1 dia') | NULL |
Combinando modificadores, o último dia do mês: vá para o dia 1, some um mês e volte um dia.
SELECT date('2026-10-14', 'start of month', '+1 month', '-1 day') AS ultimo_dia,
date('2026-02-10', 'start of month', '+1 month', '-1 day') AS ultimo_de_fevereiro;
'end of month'?
A documentação atual do SQLite (sqlite.org) já lista 'end of month', 'end of year' e 'end of day', mas eles só existem a partir da versão 3.54. No SQLite 3.50 do guia, date('2026-10-14', 'end of month') dá NULL. Use o truque acima.
Os códigos do strftime
No strftime(formato, data), cada código % do formato é trocado por uma parte da data. O resto do formato (barras, espaços, letras) sai como está. Todos os exemplos usam a quarta-feira 2026-10-14 15:30:45, a não ser quando indicado.
| Código | O que mostra | Exemplo | Resultado |
|---|---|---|---|
%Y | ano com 4 algarismos | strftime('%Y', '2026-10-14') | 2026 |
%m | mês, 01 a 12 | strftime('%m', '2026-10-14') | 10 |
%d | dia do mês, 01 a 31 | strftime('%d', '2026-10-14') | 14 |
%e | dia do mês sem o zero (com um espaço no lugar) | strftime('%e', '2026-10-05') | 5 |
%F | a data inteira, AAAA-MM-DD | strftime('%F', '2026-10-14 15:30') | 2026-10-14 |
%H | hora, 00 a 24 | strftime('%H', '2026-10-14 09:05') | 09 |
%k | hora sem o zero | strftime('%k', '2026-10-14 09:05') | 9 |
%I / %l | hora no relógio de 12 horas (com / sem o zero) | strftime('%I %p', '2026-10-14 15:30') | 03 PM |
%p / %P | AM/PM ou am/pm | strftime('%l %P', '2026-10-14 15:30') | 3 pm |
%M | minutos, 00 a 59 | strftime('%M', '2026-10-14 15:30:45') | 30 |
%S | segundos, 00 a 59 | strftime('%S', '2026-10-14 15:30:45') | 45 |
%f | segundos com milissegundos | strftime('%f', '2026-10-14 15:30:45.123') | 45.123 |
%R | HH:MM | strftime('%R', '2026-10-14 15:30:45') | 15:30 |
%T | HH:MM:SS | strftime('%T', '2026-10-14 15:30:45') | 15:30:45 |
%w | dia da semana, 0 (domingo) a 6 (sábado) | strftime('%w', '2026-10-14') | 3 (quarta) |
%u | dia da semana, 1 (segunda) a 7 (domingo) | strftime('%u', '2026-10-18') | 7 (domingo) |
%j | dia do ano, 001 a 366 | strftime('%j', '2026-10-14') | 287 |
%W | semana do ano, 00 a 53 (semanas começam na segunda) | strftime('%W', '2026-10-14') | 41 |
%U | semana do ano, 00 a 53 (semanas começam no domingo) | strftime('%U', '2026-10-14') | 41 |
%V | semana do ano no padrão ISO 8601 | strftime('%V', '2026-10-14') | 42 |
%G / %g | o ano da semana ISO (4 / 2 algarismos): o 1º de janeiro pode pertencer à última semana do ano anterior | strftime('%G', '2027-01-01') | 2026 |
%s | tempo Unix (segundos desde 1970) | strftime('%s', '2026-10-14') | 1791936000 |
%J | dia juliano | strftime('%J', '2026-10-14') | 2461327.5 |
%% | um % de verdade | strftime('%%', '2026-10-14') | % |
| (outro) | código que não existe: NULL | strftime('%Q', '2026-10-14') | NULL |
strftime devolve texto
strftime('%m', data) devolve o texto '10', e strftime('%w', data), o texto '3'. Para comparar, use aspas: WHERE strftime('%Y', data) = '2025'. Sem as aspas (= 2025), a comparação de texto com número dá falso em todas as linhas.
Contas com datas
| Para | Como | Resultado |
|---|---|---|
| dias entre duas datas | julianday('2026-10-14') - julianday('2026-10-05') | 9.0 |
| … como inteiro | CAST(julianday('2026-10-14') - julianday('2026-10-05') AS INTEGER) | 9 |
| minutos entre duas horas | (unixepoch('2026-10-14 15:30') - unixepoch('2026-10-14 08:00')) / 60 | 450 |
| diferença para gente ler | timediff('2026-10-14', '2026-10-05') | +0000-00-09 00:00:00.000 |
| vencimento em 30 dias | date('2026-10-14', '+30 days') | 2026-11-13 |
| agrupar por mês | GROUP BY strftime('%Y-%m', data) | (veja o exemplo abaixo) |
| filtrar um ano | WHERE data BETWEEN '2026-01-01' AND '2026-12-31' | (26 pedidos em 2026) |
Quantos dias cada pedido levou para ser entregue. O pedido 86 ainda não foi entregue (entregue_em é NULL), e a conta com NULL dá NULL:
SELECT id, data, entregue_em,
julianday(entregue_em) - julianday(data) AS dias
FROM pedidos
WHERE id IN (1, 2, 86);
E os pedidos de 2026, mês a mês, a partir de julho:
SELECT strftime('%Y-%m', data) AS mes, count(*) AS pedidos
FROM pedidos
WHERE data >= '2026-07-01'
GROUP BY mes;
A idade de cada cliente numa data (aqui, 18/10/2026): a diferença dos anos, menos 1 se o aniversário ainda não chegou naquele ano. A comparação entre parênteses vale 1 (verdadeiro) ou 0 (falso):
SELECT nome, nascimento,
(strftime('%Y', '2026-10-18') - strftime('%Y', nascimento))
- (strftime('%m-%d', '2026-10-18') < strftime('%m-%d', nascimento)) AS idade
FROM clientes
WHERE id <= 3;
No editor do guia
O editor roda o SQLite dentro do seu navegador. Então 'now' e CURRENT_DATE usam o relógio do seu computador, e 'localtime' usa o fuso dele: o resultado muda de leitor para leitor. É por isso que os exemplos desta página usam datas fixas.
Nos outros bancos
Os outros bancos têm tipos próprios para datas (DATE, TIMESTAMP…), e as funções mudam bastante. Conferido nas documentações oficiais do MySQL 8.4, do PostgreSQL e do SQL Server; os trechos são só para comparar.
| Para | SQLite | MySQL | PostgreSQL | SQL Server |
|---|---|---|---|---|
| agora | datetime('now'), CURRENT_TIMESTAMP | NOW() | now() | GETDATE() |
| hoje | date('now'), CURRENT_DATE | CURDATE(), CURRENT_DATE | current_date | CAST(GETDATE() AS date) |
| somar 1 dia | date(d, '+1 day') | DATE_ADD(d, INTERVAL 1 DAY) | d + interval '1 day' | DATEADD(day, 1, d) |
| dias entre datas | julianday(b) - julianday(a) | DATEDIFF(b, a) | b - a (com o tipo date) | DATEDIFF(day, a, b) |
| formatar | strftime('%d/%m/%Y', d) | DATE_FORMAT(d, '%d/%m/%Y') | to_char(d, 'DD/MM/YYYY') | FORMAT(d, 'dd/MM/yyyy') |
| só o ano | strftime('%Y', d) (texto) | YEAR(d) | EXTRACT(YEAR FROM d) | YEAR(d) |
| início do mês | date(d, 'start of month') | — | date_trunc('month', d) | — |
| último dia do mês | date(d, 'start of month', '+1 month', '-1 day') | LAST_DAY(d) | — | EOMONTH(d) |
| dia da semana | strftime('%w', d): 0 = domingo | DAYOFWEEK(d): 1 = domingo | EXTRACT(DOW FROM d): 0 = domingo | DATEPART(weekday, d) |
| tempo Unix | unixepoch(d) | UNIX_TIMESTAMP(d) | EXTRACT(EPOCH FROM d) | — |
Experimente
Missão: monte o relatório de 2025 da loja: uma linha por mês, com o mês (01 a 12) numa coluna mes e o número de pedidos numa coluna pedidos. Dica: strftime('%m', data) dá o mês, e o filtro do ano pode ser strftime('%Y', data) = '2025'.
SELECT data FROM pedidos WHERE data LIKE '2025%';
SELECT strftime('%m', data) AS mes, count(*) AS pedidos
FROM pedidos
WHERE strftime('%Y', data) = '2025'
GROUP BY mes;
Resumo
- No SQLite, datas são texto
AAAA-MM-DD(com zeros). Assim, ordenar e comparar como texto funciona. date,time,datetimeleem e normalizam;juliandayeunixepochviram números para fazer contas;strftimeformata;timediffmostra a diferença.- Modificadores, da esquerda para a direita:
'+7 days','-1 month','start of month','weekday 0','localtime'… - Tudo é em UTC, a não ser com
'localtime'. - Data ou modificador errado dá NULL, sem erro:
'14/10/2026'e'+1 dia'não funcionam. strftimedevolve texto: compare com'2025', entre aspas.