Datas e horas
Esta aula ensina a trabalhar com datas e horas em Python, cobrindo o módulo datetime, formatação com strftime e strptime, operações com timedelta e fusos horários usando zoneinfo. Inclui exemplos práticos, boas práticas e exercícios com respostas.
Nesta aula, você aprenderá a lidar com datas e horas em Python, um tópico essencial para o desenvolvimento de aplicações reais, como agendamentos, logs, relatórios e integrações com APIs. O módulo datetime é a ferramenta padrão para manipular datas e horas, e dominá-lo permite escrever código mais robusto e legível. Vamos explorar desde a criação e manipulação básica até a formatação de saídas e o trabalho com fusos horários, um desafio comum em sistemas globais.
Ao final desta aula, você será capaz de criar objetos de data e hora, realizar operações aritméticas com intervalos de tempo, formatar datas para exibição ou parsing, e lidar com fusos horários de forma correta.
datetime
O módulo datetime fornece classes para manipular datas e horas. A classe principal é datetime.datetime, que representa um ponto específico no tempo, incluindo ano, mês, dia, hora, minuto, segundo e microssegundo. Também existem as classes date (apenas data) e time (apenas hora), além de timedelta para representar diferenças entre datas.
Para criar um objeto datetime, você pode usar o construtor passando os componentes, ou usar métodos como now() e today(). O construtor aceita argumentos obrigatórios: ano, mês e dia; os demais são opcionais e assumem valores padrão (hora=0, minuto=0, etc.).
from datetime import datetime
# Criando um datetime específico
data = datetime(2025, 3, 15, 14, 30, 45)
print(data) # 2025-03-15 14:30:45
# Data e hora atuais
data_atual = datetime.now()
print(data_atual)
# Acessando componentes individuais
print(data.year, data.month, data.day)
print(data.hour, data.minute, data.second)
Além disso, você pode extrair a data ou a hora separadamente usando os métodos date() e time(). O módulo também oferece constantes como datetime.min e datetime.max, que representam os limites de valores suportados.
Formatação (strftime/strptime)
Formatar datas é uma necessidade comum para exibir em interfaces, gerar nomes de arquivos ou fazer parsing de strings. O método strftime() converte um objeto datetime em uma string usando códigos de formato. O método strptime() faz o inverso: converte uma string em um objeto datetime, dado um formato.
Os códigos de formato seguem o padrão da biblioteca C (POSIX). Alguns dos mais usados são: %Y (ano com 4 dígitos), %m (mês com 2 dígitos), %d (dia com 2 dígitos), %H (hora no formato 24h), %M (minutos), %S (segundos), %B (nome completo do mês) e %A (nome completo do dia da semana).
from datetime import datetime
data = datetime(2025, 3, 15, 14, 30, 45)
# Formatando para string
print(data.strftime("%d/%m/%Y %H:%M:%S")) # 15/03/2025 14:30:45
print(data.strftime("%d de %B de %Y")) # 15 de March de 2025
# Parsing de string para datetime
string_data = "15/03/2025 14:30"
data_parseada = datetime.strptime(string_data, "%d/%m/%Y %H:%M")
print(data_parseada) # 2025-03-15 14:30:00
É importante lembrar que strptime lança um ValueError se a string não corresponder ao formato. Portanto, é recomendado usar em blocos try/except quando houver entradas externas.
timedelta
A classe timedelta representa uma duração, ou seja, a diferença entre duas datas ou horas. Você pode criar um timedelta especificando dias, segundos, microssegundos, milissegundos, minutos, horas e semanas. A aritmética com timedelta permite somar ou subtrair intervalos de tempo de objetos datetime.
Isso é extremamente útil para cálculos como "daqui a 7 dias", "há 2 horas" ou para calcular a diferença entre dois eventos.
from datetime import datetime, timedelta
agora = datetime.now()
print("Agora:", agora)
# Adicionando 7 dias
uma_semana = agora + timedelta(days=7)
print("Daqui a 7 dias:", uma_semana)
# Subtraindo 2 horas
duas_horas_atras = agora - timedelta(hours=2)
print("Há 2 horas:", duas_horas_atras)
# Diferença entre duas datas
outra_data = datetime(2025, 12, 25)
diferenca = outra_data - agora
print("Dias até o Natal:", diferenca.days)
print("Diferença total em segundos:", diferenca.total_seconds())
Você também pode comparar timedelta e usar seus atributos como days, seconds e microseconds.
Fusos (zoneinfo)
Fusos horários são um desafio em aplicações globais. Em Python 3.9+, o módulo zoneinfo fornece acesso à base de dados de fusos horários do sistema (IANA). Com ele, você pode associar um fuso horário a um objeto datetime usando a classe ZoneInfo.
Para criar um datetime com fuso, você pode usar o método replace(tzinfo=...) ou passar o fuso no construtor. Também é possível converter entre fusos usando o método astimezone().
from datetime import datetime
from zoneinfo import ZoneInfo
# Fuso de São Paulo
fuso_sp = ZoneInfo("America/Sao_Paulo")
fuso_tokyo = ZoneInfo("Asia/Tokyo")
# Datetime com fuso
data_sp = datetime(2025, 3, 15, 14, 30, tzinfo=fuso_sp)
print("Em SP:", data_sp)
# Convertendo para Tóquio
data_tokyo = data_sp.astimezone(fuso_tokyo)
print("Em Tóquio:", data_tokyo)
# Hora atual em um fuso específico
agora_sp = datetime.now(tz=fuso_sp)
print("Agora em SP:", agora_sp)
É crucial usar fusos horários corretamente para evitar erros de cálculo, especialmente ao lidar com agendamentos e logs. Sempre que possível, armazene datas em UTC e converta para o fuso local apenas na exibição.
Boas práticas e observações finais
Ao trabalhar com datas e horas, siga estas recomendações para evitar bugs sutis:
- Prefira trabalhar com
datetimeem UTC internamente e converter para o fuso do usuário apenas na apresentação. - Use
timedeltapara cálculos relativos, em vez de manipular manualmente os componentes. - Valide entradas de string com
strptimeem blocostry/exceptpara capturar erros de formato. - Evite usar
datetime.now()sem fuso; prefiradatetime.now(tz=ZoneInfo("UTC"))para consistência. - Esteja ciente de que
timedeltanão considera mudanças de horário de verão; para cálculos em fusos específicos, considere bibliotecas comopytzoudateutilse precisar de mais controle.
Exercícios
- Crie um objeto
datetimepara a data 4 de julho de 2026, às 15h30, e imprima-o no formato "04/07/2026 15:30". - Calcule a diferença em dias entre o Natal (25/12/2025) e o Ano Novo (01/01/2026).
- Converta a string "2025-08-10 20:45:00" para um objeto
datetimee exiba o dia da semana por extenso (ex.: Sunday). - Adicione 3 semanas e 2 dias à data atual e imprima o resultado no formato ISO (YYYY-MM-DD).
- Converta a hora atual em São Paulo (America/Sao_Paulo) para o fuso de Tóquio (Asia/Tokyo) e imprima ambas.
from datetime import datetime
data = datetime(2026, 7, 4, 15, 30)
print(data.strftime("%d/%m/%Y %H:%M"))
from datetime import datetime
natal = datetime(2025, 12, 25)
ano_novo = datetime(2026, 1, 1)
diferenca = ano_novo - natal
print(diferenca.days) # 7
from datetime import datetime
data = datetime.strptime("2025-08-10 20:45:00", "%Y-%m-%d %H:%M:%S")
print(data.strftime("%A")) # Sunday
from datetime import datetime, timedelta
agora = datetime.now()
nova_data = agora + timedelta(weeks=3, days=2)
print(nova_data.date().isoformat())
from datetime import datetime
from zoneinfo import ZoneInfo
fuso_sp = ZoneInfo("America/Sao_Paulo")
fuso_tokyo = ZoneInfo("Asia/Tokyo")
agora_sp = datetime.now(tz=fuso_sp)
agora_tokyo = agora_sp.astimezone(fuso_tokyo)
print("SP:", agora_sp)
print("Tóquio:", agora_tokyo)