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 datetime em UTC internamente e converter para o fuso do usuário apenas na apresentação.
  • Use timedelta para cálculos relativos, em vez de manipular manualmente os componentes.
  • Valide entradas de string com strptime em blocos try/except para capturar erros de formato.
  • Evite usar datetime.now() sem fuso; prefira datetime.now(tz=ZoneInfo("UTC")) para consistência.
  • Esteja ciente de que timedelta não considera mudanças de horário de verão; para cálculos em fusos específicos, considere bibliotecas como pytz ou dateutil se precisar de mais controle.

Exercícios

  1. Crie um objeto datetime para a data 4 de julho de 2026, às 15h30, e imprima-o no formato "04/07/2026 15:30".
  2. ✓ Resposta:
    from datetime import datetime
    
    data = datetime(2026, 7, 4, 15, 30)
    print(data.strftime("%d/%m/%Y %H:%M"))
  3. Calcule a diferença em dias entre o Natal (25/12/2025) e o Ano Novo (01/01/2026).
  4. ✓ Resposta:
    from datetime import datetime
    
    natal = datetime(2025, 12, 25)
    ano_novo = datetime(2026, 1, 1)
    diferenca = ano_novo - natal
    print(diferenca.days)  # 7
  5. Converta a string "2025-08-10 20:45:00" para um objeto datetime e exiba o dia da semana por extenso (ex.: Sunday).
  6. ✓ Resposta:
    from datetime import datetime
    
    data = datetime.strptime("2025-08-10 20:45:00", "%Y-%m-%d %H:%M:%S")
    print(data.strftime("%A"))  # Sunday
  7. Adicione 3 semanas e 2 dias à data atual e imprima o resultado no formato ISO (YYYY-MM-DD).
  8. ✓ Resposta:
    from datetime import datetime, timedelta
    
    agora = datetime.now()
    nova_data = agora + timedelta(weeks=3, days=2)
    print(nova_data.date().isoformat())
  9. Converta a hora atual em São Paulo (America/Sao_Paulo) para o fuso de Tóquio (Asia/Tokyo) e imprima ambas.
  10. ✓ Resposta:
    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)

Referências