Python datetime
Quantos dias faltam para o Natal? Quando vence um boleto pago hoje com prazo de 30 dias? Quantos anos tem quem nasceu em 20/10/2000? A que horas em Lisboa começa uma reunião marcada para as 15h em São Paulo? Fazer essas contas "na mão" é cheio de armadilhas: meses de 28, 30 e 31 dias, anos bissextos, fusos horários. O módulo datetime ("data e hora"), que vem com o Python, já sabe tudo isso.
- Os quatro tipos do módulo:
date(data),time(hora),datetime(data e hora) etimedelta(duração). - A pegar a data e a hora de agora, e por que esse valor muda a cada execução.
- A mostrar uma data no formato brasileiro (
strftime) e a ler uma data digitada (strptime). - A contar dias entre duas datas, somar prazos e calcular a idade de alguém.
- A trabalhar com fusos horários usando
zoneinfo. - A mostrar o nome do mês e do dia da semana em português.
- Os erros reais do Python 3.14:
module 'datetime' has no attribute 'now', dia fora do mês, formato que não bate, somar número com data e comparar data com fuso com data sem fuso.
Todos os programas desta aula rodaram no Python 3.14 do computador fictício da Ana (usuária ana, computador notebook, fuso de São Paulo), na pasta pessoal dela, com python3 arquivo.py. Os que usam a data de "hoje" rodaram em 18/10/2026; no seu computador, essas saídas vão mostrar o seu dia e a sua hora.
A ideia: o calendário e o relógio da parede
Na cozinha da Ana há um calendário (que mostra o dia: 18 de outubro de 2026) e um relógio (que mostra a hora: 14h30). Juntando os dois, ela sabe o momento exato: 18/10/2026 às 14h30. E quando ela diz "o bolo leva 40 minutos" ou "o boleto vence em 30 dias", ela fala de uma duração, um pedaço de tempo que dá para somar a um momento.
| Na cozinha | No datetime | Exemplo |
|---|---|---|
| O calendário | date: ano, mês e dia | date(2026, 10, 18) |
| O relógio | time: hora, minuto, segundo | time(14, 30) |
| Calendário + relógio | datetime: um momento | datetime(2026, 10, 18, 14, 30) |
| "Daqui a 30 dias", "40 minutos" | timedelta: uma duração | timedelta(days=30) |
Os quatro moram no módulo datetime (aula Módulos e import). O jeito mais prático é importar só o que você vai usar: from datetime import date, timedelta.
1. Uma data: date
from datetime import date natal = date(2026, 12, 25) print(natal) print(natal.day, natal.month, natal.year) print(natal.weekday()) print(type(natal))
$ python3 criar.py 2026-12-25 25 12 2026 4 « 0 = segunda, 1 = terça… 4 = sexta-feira <class 'datetime.date'>
- from datetime import date
- Do módulo
datetime, traz o tipodate. - date(2026, 12, 25)
- Cria a data. A ordem é sempre ano, mês, dia (do maior para o menor), ao contrário do nosso costume de escrever 25/12/2026. Os números vão sem zero na frente:
date(2026, 8, 5), nunca08(veja Quando dá errado). - print(natal)
- Mostra no formato internacional
AAAA-MM-DD(ano-mês-dia). O formato brasileiro vem na seção 3. - .day, .month, .year
- As partes da data, como números inteiros: dia, mês, ano.
- .weekday()
- O dia da semana como número: 0 é segunda-feira e 6 é domingo. O Natal de 2026 cai numa sexta.
No modo interativo, uma data aparece de um jeito um pouco diferente: o >>> mostra o valor "como se escreve em Python", e o print mostra o valor "para gente ler":
$ python3 -q >>> from datetime import date, timedelta >>> natal = date(2026, 12, 25) >>> natal datetime.date(2026, 12, 25) >>> print(natal) 2026-12-25 >>> timedelta(days=30) datetime.timedelta(days=30) >>> natal - date(2026, 10, 18) datetime.timedelta(days=68) >>> date(2026, 10, 18) < natal True >>> exit()
As duas últimas linhas já mostram o que vem a seguir: subtrair datas dá uma duração, e datas se comparam com <, > e == como números (a data anterior é a "menor").
2. Agora: today() e now()
from datetime import date, datetime print(date.today()) print(datetime.now())
$ python3 hoje.py 2026-10-18 2026-10-18 12:18:48.599638 « horas:minutos:segundos.microssegundos
date.today()é a data de hoje, segundo o relógio do computador.datetime.now()é a data e a hora deste instante, até os microssegundos (milionésimos de segundo).
Rode o programa de novo e a hora já é outra; amanhã, a data também. Por isso as saídas acima são as do dia em que rodamos. E por isso as missões desta aula usam datas fixas, como hoje = date(2026, 10, 18): assim o resultado é sempre o mesmo e dá para conferir. Num programa de verdade você troca a data fixa por date.today(). No editor do guia, now() e today() usam o relógio e o fuso do seu navegador.
Experimente: rode várias vezes e veja os segundos mudando. Depois mostre só o ano de hoje, com date.today().year.
from datetime import date, datetime
print("Hoje:", date.today())
print("Agora:", datetime.now())
3. O formato brasileiro: strftime
Para mostrar uma data do jeito que a gente escreve, use o método strftime (de string format time, "formatar o tempo como texto"). Você passa um molde, em que cada código com % vira uma parte da data:
from datetime import datetime
consulta = datetime(2026, 11, 3, 14, 30)
print(consulta)
print(consulta.strftime("%d/%m/%Y"))
print(consulta.strftime("%d/%m/%Y às %H:%M"))
print(consulta.strftime("%d/%m/%y"))
print(f"Consulta: {consulta:%d/%m/%Y %H:%M}")
print(consulta.isoformat())
$ python3 formato.py 2026-11-03 14:30:00 03/11/2026 03/11/2026 às 14:30 03/11/26 « %y: o ano com 2 dígitos Consulta: 03/11/2026 14:30 « o mesmo molde dentro de uma f-string 2026-11-03T14:30:00 « o formato internacional (ISO 8601)
| Código | Quer dizer | Em 03/11/2026 14:30 |
|---|---|---|
%d | dia, com 2 dígitos | 03 |
%m | mês, com 2 dígitos (m minúsculo) | 11 |
%Y | ano com 4 dígitos (Y maiúsculo) | 2026 |
%y | ano com 2 dígitos | 26 |
%H | hora, de 00 a 23 | 14 |
%M | minuto (M maiúsculo) | 30 |
%S | segundo | 00 |
%A / %a | nome do dia da semana / abreviado | veja a seção 8 |
%B / %b | nome do mês / abreviado | veja a seção 8 |
Tudo o que não começa com % (as barras, o "às", os espaços) é copiado como está. O mesmo molde funciona dentro de uma f-string, depois dos dois-pontos: {consulta:%d/%m/%Y}.
Missão: o programa mostra Natal: 2026-12-25. Faça ele mostrar Natal: 25/12/2026, com strftime ou com o molde dentro de uma f-string.
from datetime import date
natal = date(2026, 12, 25)
print("Natal:", natal)
from datetime import date
natal = date(2026, 12, 25)
print("Natal:", natal.strftime("%d/%m/%Y"))
4. Lendo uma data digitada: strptime
O caminho contrário: a pessoa digita 25/12/2026 (um texto) e o programa precisa de uma data. Para isso existe datetime.strptime (de string parse time, "interpretar o texto como tempo"), com o mesmo molde:
from datetime import datetime
texto = input("Data do vencimento (dd/mm/aaaa): ")
vencimento = datetime.strptime(texto, "%d/%m/%Y").date()
print("Entendi:", vencimento)
print("Dia da semana (0 = segunda):", vencimento.weekday())
$ python3 ler_data.py Data do vencimento (dd/mm/aaaa): 25/12/2026 Entendi: 2026-12-25 Dia da semana (0 = segunda): 4
- datetime.strptime(texto, "%d/%m/%Y")
- Lê o texto seguindo o molde e devolve um
datetime(com a hora 00:00, porque o texto não tinha hora). - .date()
- Fica só com a data, sem a hora. Útil quando a hora não interessa.
O molde tem de bater exatamente com o texto. Se a pessoa digitar com traços:
$ python3 ler_data.py
Data do vencimento (dd/mm/aaaa): 25-12-2026
Traceback (most recent call last):
File "/home/ana/ler_data.py", line 4, in <module>
vencimento = datetime.strptime(texto, "%d/%m/%Y").date()
~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.14/_strptime.py", line 815, in _strptime_datetime_datetime
tt, fraction, gmtoff_fraction = _strptime(data_string, format)
~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.14/_strptime.py", line 555, in _strptime
raise ValueError("time data %r does not match format %r" %
(data_string, format))
ValueError: time data '25-12-2026' does not match format '%d/%m/%Y'
O traceback é comprido porque o erro acontece dentro do módulo (_strptime.py, um arquivo do próprio Python). Leia a primeira parte (a sua linha 4) e a última: ValueError: time data '25-12-2026' does not match format '%d/%m/%Y', "o texto '25-12-2026' não bate com o molde '%d/%m/%Y'". Num programa de verdade, você trata esse erro com try e except e pede a data de novo.
5. Contas com datas: timedelta
Quantos dias faltam
Subtrair duas datas dá uma duração, um timedelta. O número de dias está em .days:
from datetime import date
hoje = date(2026, 10, 18)
natal = date(2026, 12, 25)
falta = natal - hoje
print(falta)
print(type(falta))
print(f"Faltam {falta.days} dias para o Natal.")
$ python3 dias.py 68 days, 0:00:00 « 68 dias e 0 horas <class 'datetime.timedelta'> Faltam 68 dias para o Natal.
Se a data já passou, a diferença é negativa. Um boleto que venceu em 10/10:
from datetime import date
hoje = date(2026, 10, 18)
vencimento = date(2026, 10, 10)
diferenca = vencimento - hoje
print(diferenca)
print(diferenca.days)
if vencimento < hoje:
print(f"Boleto vencido há {-diferenca.days} dias.")
else:
print(f"Faltam {diferenca.days} dias para o vencimento.")
$ python3 boleto.py -8 days, 0:00:00 -8 Boleto vencido há 8 dias.
Missão: o aniversário da Ana é em 30/11/2026. Com hoje fixo em 18/10/2026, calcule quantos dias faltam e mostre Faltam N dias para o aniversário. com o número certo no lugar do ?.
from datetime import date
hoje = date(2026, 10, 18)
aniversario = date(2026, 11, 30)
print("Faltam ? dias para o aniversário.")
from datetime import date
hoje = date(2026, 10, 18)
aniversario = date(2026, 11, 30)
falta = aniversario - hoje
print(f"Faltam {falta.days} dias para o aniversário.")
Somar um prazo
Para "daqui a 30 dias", some uma duração criada com timedelta(days=30). O datetime cuida da virada do mês (e do ano):
from datetime import date, timedelta
compra = date(2026, 10, 18)
vence = compra + timedelta(days=30)
print("Compra:", compra.strftime("%d/%m/%Y"))
print("Vence: ", vence.strftime("%d/%m/%Y"))
print("Uma semana antes:", (vence - timedelta(weeks=1)).strftime("%d/%m/%Y"))
$ python3 vencimento.py Compra: 18/10/2026 Vence: 17/11/2026 « outubro tem 31 dias: o Python sabe Uma semana antes: 10/11/2026
O timedelta aceita weeks (semanas), days (dias), hours (horas), minutes (minutos) e seconds (segundos), sozinhos ou juntos. Com horas, use datetime (data e hora):
from datetime import datetime, timedelta
inicio = datetime(2026, 10, 18, 22, 15)
filme = timedelta(hours=2, minutes=20)
fim = inicio + filme
print("O filme acaba:", fim.strftime("%d/%m/%Y %H:%M"))
print(filme)
print(filme.total_seconds(), "segundos")
$ python3 duracao.py O filme acaba: 19/10/2026 00:35 « passou da meia-noite: virou o dia 2:20:00 8400.0 segundos
E a diferença entre dois momentos do mesmo dia dá horas e minutos. A Ana conferiu o expediente:
from datetime import datetime entrada = datetime(2026, 10, 18, 8, 0) saida = datetime(2026, 10, 18, 17, 45) trabalhado = saida - entrada print(trabalhado) print(trabalhado.total_seconds() / 3600, "horas")
$ python3 expediente.py 9:45:00 9.75 horas « 3600 segundos = 1 hora
timedelta(months=1)
Um mês não tem tamanho fixo (28, 29, 30 ou 31 dias), então o timedelta não aceita meses nem anos (veja o erro em Quando dá errado). Para "todo dia 10", crie a data direto: date(2026, 11, 10). Quando o prazo é em dias ("30 dias corridos"), o timedelta é o certo.
Missão: a loja da Ana vende com prazo de 45 dias. Para uma compra em 18/10/2026, mostre a data do vencimento no formato dd/mm/aaaa, usando timedelta.
from datetime import date, timedelta
compra = date(2026, 10, 18)
print("Compra:", compra.strftime("%d/%m/%Y"))
from datetime import date, timedelta
compra = date(2026, 10, 18)
print("Compra:", compra.strftime("%d/%m/%Y"))
vence = compra + timedelta(days=45)
print("Vence:", vence.strftime("%d/%m/%Y"))
6. A idade a partir da data de nascimento
Parece fácil: ano de hoje menos ano do nascimento. Mas quem ainda não fez aniversário este ano tem um ano a menos. A regra completa:
from datetime import date, datetime
hoje = date(2026, 10, 18)
texto = input("Data de nascimento (dd/mm/aaaa): ")
nascimento = datetime.strptime(texto, "%d/%m/%Y").date()
idade = hoje.year - nascimento.year
if (hoje.month, hoje.day) < (nascimento.month, nascimento.day):
idade -= 1
print(f"Você tem {idade} anos.")
$ python3 idade.py Data de nascimento (dd/mm/aaaa): 20/10/2000 Você tem 25 anos. « faz 26 só daqui a dois dias $ python3 idade.py Data de nascimento (dd/mm/aaaa): 18/10/2000 Você tem 26 anos. « aniversário hoje: já conta $ python3 idade.py Data de nascimento (dd/mm/aaaa): 03/05/1990 Você tem 36 anos.
- hoje.year - nascimento.year
- A conta "de cabeça": 2026 − 2000 = 26.
- (hoje.month, hoje.day)
- Uma tupla com o mês e o dia de hoje:
(10, 18). - < (nascimento.month, nascimento.day)
- Tuplas se comparam item por item: primeiro o mês; se o mês empata, o dia.
(10, 18) < (10, 20)éTrue: o aniversário deste ano ainda não chegou. - idade -= 1
- Então tira um ano.
Outra ideia que parece boa é contar os dias de vida e dividir por 365. Mas os anos bissextos têm 366 dias, e a conta escorrega perto do aniversário:
from datetime import date
hoje = date(2026, 10, 18)
nascimento = date(2000, 10, 20)
dias = (hoje - nascimento).days
print(dias, "dias")
print("Idade (dias // 365):", dias // 365)
$ python3 idade_errada.py 9494 dias Idade (dias // 365): 26 « errado: faltam 2 dias para os 26
Nesse período houve seis 29 de fevereiro (2004, 2008, 2012, 2016, 2020 e 2024), seis dias "a mais" que empurraram a conta para 26. A regra com o mês e o dia nunca erra.
7. Só a hora: time
O tipo time guarda uma hora do dia, sem data, como o horário em que a padaria abre. Com datetime.combine, você junta uma data e uma hora num momento:
from datetime import date, time, datetime
abre = time(6, 30)
print(abre)
print(abre.hour, abre.minute)
print(abre.strftime("%H:%M"))
dia = date(2026, 10, 19)
print(datetime.combine(dia, abre))
$ python3 hora.py 06:30:00 6 30 06:30 2026-10-19 06:30:00
Um time sozinho não aceita somar durações (não sabe o que fazer quando passa da meia-noite). Para contas com horas, use datetime, como no filme da seção 5.
8. Fusos horários: zoneinfo
Às 15h em São Paulo, que horas são em Lisboa? Depende da época do ano, por causa do horário de verão de lá. O módulo zoneinfo (desde o Python 3.9) conhece as regras de cada lugar do mundo, pelo nome oficial do fuso, como "America/Sao_Paulo":
from datetime import datetime
from zoneinfo import ZoneInfo
sp = ZoneInfo("America/Sao_Paulo")
reuniao = datetime(2026, 10, 18, 15, 0, tzinfo=sp)
print(reuniao)
print("Lisboa:", reuniao.astimezone(ZoneInfo("Europe/Lisbon")))
print("Tóquio:", reuniao.astimezone(ZoneInfo("Asia/Tokyo")))
print("Manaus:", reuniao.astimezone(ZoneInfo("America/Manaus")).strftime("%H:%M"))
$ python3 fuso.py 2026-10-18 15:00:00-03:00 « -03:00: três horas atrás do horário universal Lisboa: 2026-10-18 19:00:00+01:00 Tóquio: 2026-10-19 03:00:00+09:00 « em Tóquio já é o dia seguinte Manaus: 14:00
- ZoneInfo("America/Sao_Paulo")
- O fuso de São Paulo (o horário de Brasília). Os nomes são do tipo "Continente/Cidade", em inglês e com sublinhado no lugar do espaço.
- tzinfo=sp
- Diz a que fuso pertence esse momento. Um
datetimecom fuso é chamado de "consciente" (aware); sem fuso, de "ingênuo" (naive). - -03:00
- A diferença para o horário universal (UTC). O Brasil não tem horário de verão desde 2019, então São Paulo fica em −03:00 o ano todo. Lisboa, em outubro de 2026, ainda está no horário de verão (+01:00).
- .astimezone(outro_fuso)
- O mesmo instante, visto no relógio de outro lugar.
Para pegar a hora de agora já com o fuso, passe o fuso para o now(). Sem fuso, o now() devolve um momento ingênuo:
from datetime import datetime
from zoneinfo import ZoneInfo
agora = datetime.now(ZoneInfo("America/Sao_Paulo"))
print(agora.strftime("%d/%m/%Y %H:%M %Z"))
print(datetime.now().tzinfo)
$ python3 fuso_agora.py 18/10/2026 12:18 -03 « %Z: o nome curto do fuso None « sem fuso: tzinfo é None
Missão: a Ana marcou uma chamada com uma prima em Lisboa para as 10:00 de São Paulo do dia 18/10/2026. Mostre que horas serão em Lisboa, no formato HH:MM, usando astimezone.
from datetime import datetime
from zoneinfo import ZoneInfo
chamada = datetime(2026, 10, 18, 10, 0, tzinfo=ZoneInfo("America/Sao_Paulo"))
print("São Paulo:", chamada.strftime("%H:%M"))
from datetime import datetime
from zoneinfo import ZoneInfo
chamada = datetime(2026, 10, 18, 10, 0, tzinfo=ZoneInfo("America/Sao_Paulo"))
print("São Paulo:", chamada.strftime("%H:%M"))
lisboa = chamada.astimezone(ZoneInfo("Europe/Lisbon"))
print("Lisboa:", lisboa.strftime("%H:%M"))
O zoneinfo funciona no editor: quando o programa usa zoneinfo, o editor baixa a tabela de fusos (cerca de 350 kB) antes de rodar. O fuso.py acima deu no editor exatamente a mesma saída do lab.
9. Nomes de dia e mês em português
Os códigos %A (dia da semana) e %B (mês) mostram nomes. Mas, sem configuração, eles saem em inglês, mesmo num computador em português:
from datetime import date
d = date(2026, 10, 18)
print(d.strftime("%A, %d de %B de %Y"))
$ python3 nomes_ingles.py Sunday, 18 de October de 2026
O Python começa sempre com o "idioma neutro" (o locale C). Para usar o idioma configurado no sistema, que no computador da Ana é o português do Brasil (pt_BR.UTF-8), chame locale.setlocale no começo do programa:
import locale
from datetime import date
locale.setlocale(locale.LC_ALL, "")
d = date(2026, 10, 18)
print(d.strftime("%A, %d de %B de %Y"))
print(d.strftime("%a %d/%b"))
$ python3 nomes_locale.py domingo, 18 de outubro de 2026 dom 18/out
- import locale
- O módulo das configurações regionais (idioma, moeda, formato de números).
- locale.setlocale(locale.LC_ALL, "")
LC_ALL= "todas as categorias"; o texto vazio""quer dizer "use o que o sistema está usando". No terminal da Ana, isso é opt_BR.UTF-8.
O resultado do setlocale depende do sistema de quem roda: num computador configurado em inglês, os nomes continuam em inglês, e num sistema sem o pacote de idioma português pode não funcionar. No editor do guia, o setlocale é aceito sem erro, mas os nomes continuam em inglês (no editor, o mesmo nomes_locale.py mostrou Sunday, 18 de October de 2026 e Sun 18/Oct). Rode esse exemplo no seu terminal.
Quando o programa precisa mostrar português em qualquer computador (e no editor), o jeito mais seguro é ter a sua própria lista de nomes e usar o número do dia e do mês como posição (aula Acessando Itens):
from datetime import date
DIAS = ["segunda-feira", "terça-feira", "quarta-feira", "quinta-feira",
"sexta-feira", "sábado", "domingo"]
MESES = ["janeiro", "fevereiro", "março", "abril", "maio", "junho", "julho",
"agosto", "setembro", "outubro", "novembro", "dezembro"]
d = date(2026, 10, 18)
print(f"{DIAS[d.weekday()]}, {d.day} de {MESES[d.month - 1]} de {d.year}")
$ python3 nomes_lista.py domingo, 18 de outubro de 2026
d.weekday() vai de 0 (segunda) a 6 (domingo), a mesma ordem da lista DIAS. Os meses vão de 1 a 12, mas as posições da lista começam em 0: por isso o - 1. O editor mostrou a mesma linha.
Formas diferentes de mostrar e de ler datas
| Para | Forma | Quando usar |
|---|---|---|
| Mostrar | d.strftime("%d/%m/%Y") | O jeito clássico; funciona em qualquer versão |
| Mostrar | f"{d:%d/%m/%Y}" | Quando a data vai no meio de um texto maior: o molde fica dentro da f-string |
| Mostrar | print(d) ou d.isoformat() | Para arquivos, nomes de arquivo e outros programas: 2026-12-25 é o formato internacional e se ordena certo como texto |
| Ler | datetime.strptime(texto, "%d/%m/%Y") | Texto no formato brasileiro (ou qualquer outro molde) |
| Ler | date.fromisoformat("2026-12-25") | Texto no formato internacional (de um arquivo, de um banco de dados) |
| Criar | date(2026, 12, 25) | Quando você já tem os números |
Quando dá errado
import datetime e depois datetime.now()
O erro mais famoso do módulo. O módulo se chama datetime, e o tipo dentro dele também:
import datetime print(datetime.now())
$ python3 erro_modulo.py
Traceback (most recent call last):
File "/home/ana/erro_modulo.py", line 3, in <module>
print(datetime.now())
^^^^^^^^^^^^
AttributeError: module 'datetime' has no attribute 'now'
"O módulo datetime não tem o atributo now". Com import datetime, o nome datetime é o módulo inteiro, e o now é do tipo que está dentro dele. Como consertar: escolha um dos dois jeitos e não misture: import datetime + datetime.datetime.now(), ou (o jeito desta aula) from datetime import datetime + datetime.now().
from datetime import date print(date(2026, 2, 30))
$ python3 erro_dia.py
Traceback (most recent call last):
File "/home/ana/erro_dia.py", line 3, in <module>
print(date(2026, 2, 30))
~~~~^^^^^^^^^^^^^
ValueError: day 30 must be in range 1..28 for month 2 in year 2026
"O dia 30 tem de estar entre 1 e 28 no mês 2 do ano 2026". O Python 3.14 diz até o limite certo daquele mês (2026 não é bissexto). Com o mês errado, a mensagem é parecida:
$ python3 erro_mes.py
Traceback (most recent call last):
File "/home/ana/erro_mes.py", line 3, in <module>
print(date(2026, 13, 1))
~~~~^^^^^^^^^^^^^
ValueError: month must be in 1..12, not 13
Atenção à ordem: date(25, 12, 2026) não é 25/12/2026. A ordem é ano, mês, dia.
from datetime import date print(date(2026, 08, 5))
$ python3 erro_zero.py
File "/home/ana/erro_zero.py", line 3
print(date(2026, 08, 5))
^
SyntaxError: leading zeros in decimal integer literals are not permitted; use an 0o prefix for octal integers
"Zeros à esquerda em números inteiros não são permitidos" (o resto da mensagem fala de números octais, que não têm nada a ver com datas). O costume de escrever "08" vem do papel. Como consertar: date(2026, 8, 5). O zero só aparece na hora de mostrar, com %d e %m.
strptime
from datetime import datetime
print(datetime.strptime("25/12/2026 10:00", "%d/%m/%Y"))
$ python3 erro_sobra.py
Traceback (most recent call last):
File "/home/ana/erro_sobra.py", line 3, in <module>
print(datetime.strptime("25/12/2026 10:00", "%d/%m/%Y"))
~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.14/_strptime.py", line 815, in _strptime_datetime_datetime
tt, fraction, gmtoff_fraction = _strptime(data_string, format)
~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.14/_strptime.py", line 558, in _strptime
raise ValueError("unconverted data remains: %s" %
data_string[found.end():])
ValueError: unconverted data remains: 10:00
"Sobrou texto sem converter: 10:00". O molde leu a data e encontrou mais coisa depois. Como consertar: o molde tem de cobrir o texto inteiro: "%d/%m/%Y %H:%M". (O outro caso, texto com traços e molde com barras, está na seção 4: does not match format.)
from datetime import date print(date(2026, 10, 18) + 30)
$ python3 erro_soma.py
Traceback (most recent call last):
File "/home/ana/erro_soma.py", line 3, in <module>
print(date(2026, 10, 18) + 30)
~~~~~~~~~~~~~~~~~~~^~~~
TypeError: unsupported operand type(s) for +: 'datetime.date' and 'int'
"Tipos não suportados para +: date e int". 30 o quê? Dias, horas, segundos? O Python não adivinha. Como consertar: date(2026, 10, 18) + timedelta(days=30). E o timedelta não aceita meses:
$ python3 erro_meses.py
Traceback (most recent call last):
File "/home/ana/erro_meses.py", line 3, in <module>
print(timedelta(months=1))
~~~~~~~~~^^^^^^^^^^
TypeError: __new__() got an unexpected keyword argument 'months'
"Recebeu um argumento inesperado, months". O __new__() é o nome interno de quem cria o timedelta; o que importa é o fim: months não existe.
%M no lugar de %m (sem mensagem de erro)
from datetime import datetime
consulta = datetime(2026, 11, 3, 14, 30)
print(consulta.strftime("%d/%M/%Y"))
$ python3 erro_minuto.py 03/30/2026 « 30 é o minuto, não o mês!
%M (maiúsculo) é o minuto; o mês é %m (minúsculo). O Python não reclama, porque as duas coisas existem. Num date sem hora, %M dá sempre 00. Para lembrar: minúsculo para o mês (que é "menor" que o ano, %Y maiúsculo); %H:%M para a hora, tudo maiúsculo.
from zoneinfo import ZoneInfo
print(ZoneInfo("America/SaoPaulo"))
O traceback é enorme (quase 40 linhas, de dentro da biblioteca). As linhas que importam são as últimas:
$ python3 erro_fuso_nome.py
Traceback (most recent call last):
File "/usr/lib/python3.14/zoneinfo/_common.py", line 12, in load_tzdata
path = resources.files(package_name).joinpath(resource_name)
~~~~~~~~~~~~~~~^^^^^^^^^^^^^^
… « (linhas de dentro da biblioteca, cortadas aqui)
ModuleNotFoundError: No module named 'tzdata'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/ana/erro_fuso_nome.py", line 3, in <module>
print(ZoneInfo("America/SaoPaulo"))
~~~~~~~~^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.14/zoneinfo/_common.py", line 29, in load_tzdata
raise ZoneInfoNotFoundError(f"No time zone found with key {key}")
zoneinfo._common.ZoneInfoNotFoundError: 'No time zone found with key America/SaoPaulo'
São dois erros encadeados. O Python não achou o fuso nos arquivos do sistema, tentou a reserva (o pacote tzdata, que o Ubuntu não precisa ter instalado) e também não achou. A mensagem final é a que importa: "nenhum fuso encontrado com a chave America/SaoPaulo". O nome certo tem sublinhado: America/Sao_Paulo. Os nomes seguem a lista oficial de fusos (a "base de dados da IANA"); na dúvida, procure "lista de fusos tz database".
from datetime import datetime
from zoneinfo import ZoneInfo
prazo = datetime(2026, 10, 18, 18, 0)
agora = datetime(2026, 10, 18, 15, 0, tzinfo=ZoneInfo("America/Sao_Paulo"))
print(agora < prazo)
$ python3 erro_naive.py
Traceback (most recent call last):
File "/home/ana/erro_naive.py", line 6, in <module>
print(agora < prazo)
^^^^^^^^^^^^^
TypeError: can't compare offset-naive and offset-aware datetimes
"Não dá para comparar datetimes ingênuos (sem fuso) com conscientes (com fuso)". As 18h do prazo são 18h de onde? O Python se recusa a supor. A subtração dá um erro parecido. Como consertar: ponha o fuso nos dois (tzinfo=... no prazo também), ou em nenhum. Num programa, escolha uma regra e siga sempre.
Referência rápida
| Escrita | O que faz |
|---|---|
from datetime import date, time, datetime, timedelta | Traz os quatro tipos |
date(2026, 12, 25) | Uma data (ano, mês, dia) |
datetime(2026, 11, 3, 14, 30) | Data e hora |
time(6, 30) | Só a hora |
date.today() / datetime.now() | Hoje / agora (mudam a cada execução) |
d.day, d.month, d.year, d.weekday() | Dia, mês, ano, dia da semana (0 = segunda) |
d.strftime("%d/%m/%Y") / f"{d:%d/%m/%Y}" | Data → texto no formato brasileiro |
datetime.strptime(t, "%d/%m/%Y") | Texto → datetime (.date() para só a data) |
d2 - d1 | A duração entre duas datas (.days, .total_seconds()) |
d + timedelta(days=30) | Somar um prazo (também weeks, hours, minutes, seconds) |
datetime.combine(d, t) | Junta data e hora |
ZoneInfo("America/Sao_Paulo") | Um fuso horário (from zoneinfo import ZoneInfo) |
datetime(…, tzinfo=fuso) / datetime.now(fuso) | Momento com fuso |
m.astimezone(outro_fuso) | O mesmo instante no relógio de outro lugar |
locale.setlocale(locale.LC_ALL, "") | Nomes de mês e dia no idioma do sistema (%A, %B); não funciona no editor |
| Mensagem | Causa provável |
|---|---|
AttributeError: module 'datetime' has no attribute 'now' | import datetime + datetime.now(): use from datetime import datetime |
ValueError: day 30 must be in range 1..28 for month 2 in year 2026 | Data que não existe (ou ordem trocada: é ano, mês, dia) |
ValueError: month must be in 1..12, not 13 | Mês fora de 1 a 12 |
SyntaxError: leading zeros in decimal integer literals are not permitted | 08 no lugar de 8 |
ValueError: time data '…' does not match format '…' | O texto não segue o molde do strptime |
ValueError: unconverted data remains: … | O texto tem mais coisa que o molde |
TypeError: unsupported operand type(s) for +: 'datetime.date' and 'int' | Somou um número: use timedelta(days=…) |
TypeError: __new__() got an unexpected keyword argument 'months' | timedelta não tem meses nem anos |
ZoneInfoNotFoundError: 'No time zone found with key …' | Nome de fuso errado (é America/Sao_Paulo) |
TypeError: can't compare offset-naive and offset-aware datetimes | Um momento com fuso e outro sem |
Mês saiu como 30, sem erro | %M (minuto) no lugar de %m (mês) |
Nomes em inglês (Sunday, October) | Faltou o locale.setlocale, ou o sistema (ou o editor) não está em português |
Exercícios
1. O molde brasileiro
Complete o molde para mostrar 25/12/2026:
2. Daqui a uma semana
Complete o argumento para somar 7 dias:
3. O dia da semana
Que número date(2026, 10, 19).weekday() devolve, sabendo que 18/10/2026 é um domingo?
4. Qual destas linhas cria a data 5 de agosto de 2026?
5. O que (date(2026, 12, 25) - date(2026, 10, 18)).days vale?
6. Por que uma missão do guia nunca usa date.today() na meta?
7. Com import datetime, como se pega a hora de agora?
Missão final: a idade certa
Missão: este programa calcula a idade dividindo os dias por 365, e erra: para quem nasceu em 20/10/2000 (a entrada preparada), com hoje fixo em 18/10/2026, ele diz 26 anos, mas a pessoa ainda tem 25. Troque a conta pela regra da seção 6 (ano menos ano, menos 1 se o aniversário deste ano ainda não chegou). A saída tem de ser Você tem 25 anos.
from datetime import date, datetime
hoje = date(2026, 10, 18)
texto = input("Data de nascimento (dd/mm/aaaa): ")
nascimento = datetime.strptime(texto, "%d/%m/%Y").date()
idade = (hoje - nascimento).days // 365
print(f"Você tem {idade} anos.")
from datetime import date, datetime
hoje = date(2026, 10, 18)
texto = input("Data de nascimento (dd/mm/aaaa): ")
nascimento = datetime.strptime(texto, "%d/%m/%Y").date()
idade = hoje.year - nascimento.year
if (hoje.month, hoje.day) < (nascimento.month, nascimento.day):
idade -= 1
print(f"Você tem {idade} anos.")
Depois de cumprir, troque a entrada por 18/10/2000 (aniversário "hoje": 26 anos) e por 29/02/2000, uma data que só existe em ano bissexto. E, no seu terminal, troque date(2026, 10, 18) por date.today() para ter a idade de verdade.
Resumo
- O módulo
datetimetem quatro tipos:date(data),time(hora),datetime(data e hora) etimedelta(duração). Importe comfrom datetime import …. - Datas se criam na ordem ano, mês, dia, sem zeros na frente:
date(2026, 8, 5). date.today()edatetime.now()mudam a cada execução: use datas fixas para testar.strftime("%d/%m/%Y")mostra no formato brasileiro;strptime(texto, "%d/%m/%Y")lê. O molde tem de bater com o texto.%mé mês,%Mé minuto.- Data menos data dá um
timedelta(.days); data maistimedelta(days=30)dá outra data. Não existetimedeltade meses. - Idade: ano menos ano, e menos 1 se o aniversário deste ano ainda não chegou. Dividir os dias por 365 erra.
- Fusos:
ZoneInfo("America/Sao_Paulo"),tzinfo=…e.astimezone(…). Não misture momentos com e sem fuso. - Nomes de mês e dia saem em inglês;
locale.setlocale(locale.LC_ALL, "")usa o idioma do sistema (no terminal; no editor, não). Para português em qualquer lugar, use a sua lista de nomes.