A manipulação de datas e horas é uma das tarefas mais comuns no desenvolvimento de software. Seja para registrar eventos, calcular intervalos de tempo, formatar saídas para usuários ou lidar com fusos horários, o módulo datetime do Python é a ferramenta essencial que todo desenvolvedor precisa dominar.
Neste guia completo, você aprenderá desde os conceitos básicos até técnicas avançadas de manipulação de temporal data em Python, com exemplos práticos que você pode aplicar imediatamente em seus projetos.
📦 Introdução ao Módulo datetime
O Python possui o módulo datetime integrado à sua biblioteca padrão, o que significa que você não precisa instalar nada extra para começar a usá-lo. Este módulo fornece classes para trabalhar com datas, horas e combinações de ambos.
Segundo a documentação oficial do Python, o módulo datetime oferece várias classes fundamentais que tornam a manipulação de dados temporais simples e intuitiva.
import datetime
# Verificar versão do módulo
print(datetime.__version__)
🕐 As Principais Classes do datetime
1. datetime.date — Apenas a Data
A classe date representa uma data no formato ano-mês-dia, sem informação de horário. É ideal quando você precisa trabalhar apenas com calendários, anniversários, prazos, etc.
import datetime
# Criar uma data específica
data_nascimento = datetime.date(1995, 3, 15)
print(data_nascimento) # 1995-03-15
# Obter a data de hoje
hoje = datetime.date.today()
print(f"Hoje é {hoje}") # Hoje é 2026-05-13
# Acessar componentes individuais
print(f"Ano: {hoje.year}") # 2026
print(f"Mês: {hoje.month}") # 5
print(f"Dia: {hoje.day}") # 13
print(f"Dia da semana: {hoje.weekday()}") # 0 (segunda-feira)
# Dia da semana com nome
dias = ["Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado", "Domingo"]
print(f"Hoje é {dias[hoje.weekday()]}")
# Criar data a partir de timestamp Unix
data_timestamp = datetime.date.fromtimestamp(1700000000)
print(data_timestamp)
2. datetime.time — Apenas o Horário
A classe time representa um horário específico, sem informação de data. Útil para agendamentos, lembretes e controle de ponto.
import datetime
# Criar um horário específico
hora_reuniao = datetime.time(14, 30, 0) # 14h30min
print(hora_reuniao) # 14:30:00
# Com microsegundos
hora_exata = datetime.time(14, 30, 45, 123456)
print(hora_exata) # 14:30:45.123456
# Acessar componentes
print(f"Hora: {hora_reuniao.hour}") # 14
print(f"Minutos: {hora_reuniao.minute}") # 30
print(f"Segundos: {hora_reuniao.second}") # 0
# Formatar horário
print(hora_reuniao.strftime("%H:%M")) # 14:30
print(hora_reuniao.strftime("%I:%M %p")) # 02:30 PM
3. datetime.datetime — Data e Hora Combinados
A classe datetime é a mais usada e completa, combinando data e hora em um único objeto. É perfect para timestamps, logs, registros de eventos e muito mais.
import datetime
# Criar datetime específico
agora = datetime.datetime.now()
print(f"Agora: {agora}")
# Criar datetime específico
evento = datetime.datetime(2026, 12, 25, 18, 0, 0)
print(f"Christmas: {evento}")
# datetime atual com timezone
utc_atual = datetime.datetime.utcnow()
print(f"UTC agora: {utc_atual}")
# Criar a partir de string
data_str = "2026-05-13 15:30:00"
data_parsed = datetime.datetime.strptime(data_str, "%Y-%m-%d %H:%M:%S")
print(f"Parseado: {data_parsed}")
# Acessar todos os componentes
print(f"Data: {agora.date()}")
print(f"Hora: {agora.time()}")
print(f"Ano: {agora.year}, Mês: {agora.month}, Dia: {agora.day}")
print(f"Hora: {agora.hour}, Minuto: {agora.minute}, Segundo: {agora.second}")
4. datetime.timedelta — Diferenças de Tempo
A classe timedelta representa a diferença entre duas datas ou horas. É essencial para calcular durações, intervalos e fazer operações aritméticas com datas.
import datetime
# Criar timedelta
um_dia = datetime.timedelta(days=1)
duas_horas = datetime.timedelta(hours=2)
meia_hora = datetime.timedelta(minutes=30)
# Operações com datetime
hoje = datetime.datetime.now()
amanha = hoje + um_dia
print(f"Amanhã: {amanha}")
semana_passada = hoje - datetime.timedelta(weeks=1)
print(f"Semana passada: {semana_passada}")
# Calcular diferença entre datas
inicio = datetime.datetime(2026, 1, 1)
fim = datetime.datetime(2026, 5, 13)
diff = fim - inicio
print(f"Diferença: {diff}")
print(f"Dias: {diff.days}")
print(f"Segundos: {diff.seconds}")
# timedelta total em horas
total_horas = diff.total_seconds() / 3600
print(f"Total de horas: {total_horas:.2f}")
📝 Formatação de Datas e Horas
A formatação de datas é crucial para exibir informações aos usuários de manera clara e compreensível. O Python oferece duas funções principais para isso: strftime() para formatar datetime em string e strptime() para converter string em datetime.
Códigos de Formato Mais Usados
import datetime
agora = datetime.datetime.now()
# Formatos comuns
print(agora.strftime("%d/%m/%Y")) # 13/05/2026
print(agora.strftime("%d-%m-%Y")) # 13-05-2026
print(agora.strftime("%d de %B de %Y")) # 13 de maio de 2026
print(agora.strftime("%H:%M:%S")) # 14:30:45
print(agora.strftime("%H:%M")) # 14:30
print(agora.strftime("%d/%m/%Y às %H:%M")) # 13/05/2026 às 14:30
# Formatos internacionais
print(agora.strftime("%Y-%m-%d")) # 2026-05-13 (ISO 8601)
print(agora.strftime("%B %d, %Y")) # May 13, 2026
# Dia da semana
print(agora.strftime("%A")) # quarta-feira
print(agora.strftime("%a")) # qua
print(agora.strftime("%A, %d de %B de %Y")) # quarta-feira, 13 de maio de 2026
# Mês
print(agora.strftime("%B")) # maio
print(agora.strftime("%b") # mai
print(agora.strftime("%m")) # 05
# Hora em formato 12h
print(agora.strftime("%I:%M %p")) # 02:30 PM
Para uma referência completa de todos os códigos de formatação, a W3Schools oferece um guia útil e didático sobre datetime em Python.
🔄 Conversão de String para datetime
Uma das tarefas mais frequentes em programação é converter strings em formato variados para objetos datetime. O strptime() (string parse time) faz exatamente isso.
import datetime
#various formatos de entrada
formatos = [
("2026-05-13", "%Y-%m-%d"),
("13/05/2026", "%d/%m/%Y"),
("13-05-2026", "%d-%m-%Y"),
("May 13, 2026", "%B %d, %Y"),
("13 May 2026", "%d %B %Y"),
("2026-05-13 14:30:00", "%Y-%m-%d %H:%M:%S"),
("13/05/2026 14:30", "%d/%m/%Y %H:%M"),
]
for data_str, formato in formatos:
try:
dt = datetime.datetime.strptime(data_str, formato)
print(f"'{data_str}' -> {dt}")
except ValueError as e:
print(f"Erro ao converter '{data_str}': {e}")
# Função para detectar formato automaticamente
def converter_data(data_str):
formatos = [
"%Y-%m-%d",
"%d/%m/%Y",
"%d-%m-%Y",
"%Y/%m/%d",
"%B %d, %Y",
"%d %B %Y",
]
for fmt in formatos:
try:
return datetime.datetime.strptime(data_str, fmt)
except ValueError:
continue
raise ValueError(f"Não foi possível converter: {data_str}")
print(converter_data("13/05/2026"))
🌍 Trabalhando com Fusos Horários
Lidar com fusos horários é um dos aspectos mais complexos da manipulação de datas. O Python usa a biblioteca pytz para gerenciar fusos horários de forma eficiente.
import datetime
import pytz
# Criar datetime com timezone
tz_brasil = pytz.timezone('America/Sao_Paulo')
tz_eua = pytz.timezone('America/New_York')
tz_japao = pytz.timezone('Asia/Tokyo')
# Datetime atual em diferentes fusos
agora_brasil = datetime.datetime.now(tz_brasil)
agora_eua = datetime.datetime.now(tz_eua)
agora_japao = datetime.datetime.now(tz_japao)
print(f"Brasil: {agora_brasil}")
print(f"EUA: {agora_eua}")
print(fJapão: {agora_japao}")
# Criar datetime em timezone específico
data_especifica = datetime.datetime(2026, 12, 25, 18, 0, 0, tzinfo=tz_brasil)
print(f"Natal no Brasil: {data_especifica}")
# Converter entre fusos horários
natal_brasil = datetime.datetime(2026, 12, 25, 18, 0, 0, tzinfo=tz_brasil)
natal_eua = natal_brasil.astimezone(tz_eua)
natal_japao = natal_brasil.astimezone(tz_japao)
print(f"Natal 18h no Brasil = {natal_eua.strftime('%H:%M')} nos EUA")
print(f"Natal 18h no Brasil = {natal_japao.strftime('%H:%M')} no Japão")
# Obter timezone de uma string ISO 8601
data_iso = "2026-05-13T14:30:00-03:00"
dt_iso = datetime.datetime.fromisoformat(data_iso)
print(f"De ISO: {dt_iso}")
# Lista de fusos disponíveis
print("Alguns fusos horários disponíveis:")
for tz in ['America/Sao_Paulo', 'America/New_York', 'Europe/London', 'Asia/Tokyo', 'Australia/Sydney']:
print(f" - {tz}")
A documentação do Real Python oferece um guia detalhado sobre como trabalhar com fusos horários de manera correta.
📊 Operações Aritméticas com Datas
Uma das grandes vantagens do módulo datetime é a capacidade de realizar operações aritméticas diretamente entre datas e intervalos de tempo.
import datetime
# Adição e subtração
data = datetime.datetime(2026, 5, 13)
# Adicionar dias
mais_10_dias = data + datetime.timedelta(days=10)
print(f"10 dias depois: {mais_10_dias}")
# Subtrair semanas
menos_2_semanas = data - datetime.timedelta(weeks=2)
print(f"2 semanas antes: {menos_2_semanas}")
# Adicionar meses (precisa de biblioteca adicional ou lógica personalizada)
def adicionar_meses(data, meses):
mes = data.month + meses
ano = data.year + (mes - 1) // 12
mes = ((mes - 1) % 12) + 1
dia = min(data.day, [31, 29 if ano % 4 == 0 and (ano % 100 != 0 or ano % 400 == 0) else 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][mes-1])
return data.replace(year=ano, month=mes, day=dia)
resultado = adicionar_meses(data, 6)
print(f"6 meses depois: {resultado}")
# Calcular idade
def calcular_idade(data_nascimento):
hoje = datetime.date.today()
idade = hoje.year - data_nascimento.year
if (hoje.month, hoje.day) < (data_nascimento.month, data_nascimento.day):
idade -= 1
return idade
nasc = datetime.date(1995, 3, 15)
print(f"Idade: {calcular_idade(nasc)} anos")
# Verificar se é dia útil
def eh_dia_util(data):
return data.weekday() < 5 # 0-4 = seg a sex
print(f"13/05/2026 é dia útil? {eh_dia_util(data)}")
🗓️ Gerando Sequências de Datas
Para muitas aplicações, você precisa gerar sequências de datas, como por exemplo, criar uma agenda, gerar relatórios por período ou iterar sobre dias úteis.
import datetime
# Gerar sequência de dias
inicio = datetime.date(2026, 5, 1)
fim = datetime.date(2026, 5, 15)
dias = []
data = inicio
while data <= fim:
dias.append(data)
data += datetime.timedelta(days=1)
print("Dias de maio (1-15):")
for d in dias:
print(f" {d.strftime('%d/%m')}")
# Usando list comprehension
dias_maio = [inicio + datetime.timedelta(days=i) for i in range(15)]
print(f"Total de dias: {len(dias_maio)}")
# Gerar meses entre datas
def meses_entre(inicio, fim):
resultado = []
atual = inicio
while atual < fim:
resultado.append(atual)
if atual.month == 12:
atual = atual.replace(year=atual.year + 1, month=1)
else:
atual = atual.replace(month=atual.month + 1)
return resultado
meses = meses_entre(datetime.date(2026, 1, 1), datetime.date(2026, 12, 31))
print("Meses de 2026:")
for m in meses:
print(f" {m.strftime('%B')}")
# Dias úteis entre datas
def dias_uteis(inicio, fim):
dias = []
data = inicio
while data <= fim:
if data.weekday() < 5:
dias.append(data)
data += datetime.timedelta(days=1)
return dias
uteis = dias_uteis(datetime.date(2026, 5, 1), datetime.date(2026, 5, 31))
print(f"Dias úteis em maio: {len(uteis)}")
# Gerar horários para um dia específico
def horarios_dia(data, inicio_hora=9, fim_hora=18, intervalo=30):
horarios = []
for h in range(inicio_hora, fim_hora):
for m in [0, intervalo]:
if h == fim_hora - 1 and m > 0:
break
horarios.append(data.replace(hour=h, minute=m))
return horarios
agenda = horarios_dia(datetime.datetime(2026, 5, 13))
print("Horários disponíveis para 13/05:")
for h in agenda[:6]:
print(f" {h.strftime('%H:%M')}")
🔍 Comparação de Datas
Comparar datas é essencial para validações, ordenações e verificações de período. O datetime permite várias formas de comparação.
import datetime
# Datas de exemplo
d1 = datetime.datetime(2026, 5, 13)
d2 = datetime.datetime(2026, 6, 15)
d3 = datetime.datetime(2026, 5, 13, 14, 30)
# Comparações diretas
print(f"d1 == d2: {d1 == d2}") # False
print(f"d1 != d2: {d1 != d2}") # True
print(f"d1 < d2: {d1 < d2}") # True
print(f"d1 <= d2: {d1 <= d2}") # True
print(f"d1 > d2: {d1 > d2}") # False
# Comparar apenas datas (ignorando hora)
print(f"d1.date() == d3.date(): {d1.date() == d3.date()}") # True
# Verificar se está no passado, presente ou futuro
agora = datetime.datetime.now()
if agora < d1:
print("d1 está no futuro")
elif agora > d1:
print("d1 está no passado")
else:
print("d1 é agora")
# Verificar se está em um intervalo
inicio = datetime.datetime(2026, 1, 1)
fim = datetime.datetime(2026, 12, 31)
print(f"d1 está entre {inicio.date()} e {fim.date()}? {inicio <= d1 <= fim}")
# Ordenar lista de datas
datas = [
datetime.datetime(2026, 3, 15),
datetime.datetime(2026, 1, 10),
datetime.datetime(2026, 12, 25),
datetime.datetime(2026, 7, 4),
]
datas.sort()
print("Datas ordenadas:")
for d in datas:
print(f" {d.strftime('%d/%m/%Y')}")
⏰ Medindo Tempo de Execução
O datetime é frequentemente usado para medir o tempo de execução de código, o que é fundamental para otimização de performance.
import datetime
import time
# Método 1: Usando datetime
inicio = datetime.datetime.now()
time.sleep(1) # Simulando processamento
fim = datetime.datetime.now()
duracao = fim - inicio
print(f"Duração: {duracao.total_seconds():.2f} segundos")
# Método 2: Usando time.time()
inicio_ts = time.time()
time.sleep(0.5)
fim_ts = time.time()
print(f"Duração (time): {fim_ts - inicio_ts:.2f} segundos")
# Método 3: Usando context manager
class Cronometro:
def __init__(self):
self.inicio = None
self.fim = None
def __enter__(self):
self.inicio = datetime.datetime.now()
return self
def __exit__(self, *args):
self.fim = datetime.datetime.now()
self.duracao = self.fim - self.inicio
def tempo_total(self):
return self.duracao.total_seconds()
with Cronometro() as cron:
time.sleep(0.3)
print(f"Tempo medido: {cron.tempo_total():.3f} segundos")
# Medir múltiplas execuções
def medir_funcao(func, vezes=100):
resultados = []
for _ in range(vezes):
inicio = datetime.datetime.now()
func()
fim = datetime.datetime.now()
resultados.append((fim - inicio).total_seconds())
media = sum(resultados) / len(resultados)
return {
'media': media,
'min': min(resultados),
'max': max(resultados),
'vezes': vezes
}
def funcao_teste():
soma = 0
for i in range(1000):
soma += i
resultado = medir_funcao(funcao_teste, vezes=50)
print(f"Média: {resultado['media']*1000:.2f}ms")
print(f"Mín: {resultado['min']*1000:.2f}ms, Máx: {resultado['max']*1000:.2f}ms")
🛠️ Casos de Uso Práticos
1. Calcular dias até uma data futura
import datetime
def dias_ate(alvo):
hoje = datetime.date.today()
if isinstance(alvo, datetime.datetime):
alvo = alvo.date()
diff = alvo - hoje
return diff.days
# Aniversário
aniversario = datetime.date(2026, 12, 25)
print(f"Dias até o Natal: {dias_ate(aniversario)}")
# Feriado
feriado = datetime.date(2027, 1, 1)
print(f"Dias até o Ano Novo: {dias_ate(feriado)}")
2. Verificar se um ano é bissexto
import datetime
def eh_bissexto(ano):
return (ano % 4 == 0 and ano % 100 != 0) or (ano % 400 == 0)
# Mês de fevereiro em diferentes anos
for ano in [2024, 2025, 2026, 2028]:
print(f"{ano}: {'Bissexto' if eh_bissexto(ano) else 'Normal'}")
# Usando dateutil
from datetime import date
import calendar
print(f"Fevereiro 2024 tem {calendar.monthrange(2024, 2)[1]} dias")
3. Gerar nome de arquivo com timestamp
import datetime
def gerar_nome_arquivo(prefixo, extensao):
agora = datetime.datetime.now()
timestamp = agora.strftime("%Y%m%d_%H%M%S")
return f"{prefixo}_{timestamp}.{extensao}"
print(gerar_nome_arquivo("backup", "zip"))
print(gerar_nome_arquivo("relatorio", "pdf"))
print(gerar_nome_arquivo("log", "txt"))
4. Calcular duração de um evento
import datetime
eventos = [
("Reunião", datetime.datetime(2026, 5, 13, 14, 0), datetime.datetime(2026, 5, 13, 15, 30)),
("Workshop", datetime.datetime(2026, 5, 13, 9, 0), datetime.datetime(2026, 5, 13, 12, 0)),
("Palestra", datetime.datetime(2026, 5, 13, 16, 0), datetime.datetime(2026, 5, 13, 17, 45)),
]
for nome, inicio, fim in eventos:
duracao = fim - inicio
print(f"{nome}: {duracao} ({duracao.total_seconds()/3600:.2f}h)")
5. Validar data de expiration
import datetime
def esta_expirado(data_expiracao):
return datetime.datetime.now() > data_expiracao
# Simular certidicado SSL
certificado_expira = datetime.datetime(2026, 12, 31, 23, 59, 59)
print(f"Certificado expirado? {esta_expirado(certificado_expira)}")
# Verificar dias restantes
def dias_para_expirar(data_expiracao):
agora = datetime.datetime.now()
if isinstance(data_expiracao, datetime.datetime):
data_expiracao = data_expiracao.replace(tzinfo=None) - agora
else:
data_expiracao = data_expiracao - agora.date()
return data_expiracao.days
print(f"Dias até expirar: {dias_para_expirar(certificado_expira)}")
📚 Bibliotecas Complementares
Embora o módulo datetime seja extremamente poderoso, existem bibliotecas que podem facilitar ainda mais o trabalho com datas em Python.
dateutil - Extensões úteis
# dateutil fornece funcionalidades avançadas
from dateutil import parser
from dateutil.relativedelta import relativedelta
from dateutil.rrule import rrule, MONTHLY
# Parse automático de strings
data = parser.parse("amanhã")
print(f"Parseado: {data}")
data = parser.parse("15 de maio de 2026")
print(f"Parseado: {data}")
# Adicionar meses relativedelta
from datetime import datetime
agora = datetime.now()
mais_3_meses = agora + relativedelta(months=3)
print(f"3 meses depois: {mais_3_meses}")
# Gerar ocorrências mensais
from dateutil.rrule import rrule, MONTHLY
inicio = datetime(2026, 1, 1)
fim = datetime(2026, 12, 31)
ocorrencias = list(rrule(MONTHLY, dtstart=inicio, until=fim))
print(f"Meses de 2026: {len(ocorrencias)}")
pandas - Para séries temporais
Para análise de dados e séries temporais, o pandas é a biblioteca mais recomendada. Ela oferece funcionalidades avançadas para manipulação de datas em contextos de análise de dados.
import pandas as pd
# Criar DataFrame com datas
datas = pd.date_range(start='2026-01-01', end='2026-12-31', freq='D')
df = pd.DataFrame({'data': datas, 'valor': range(len(datas))})
# Operações de tempo
df['ano'] = df['data'].dt.year
df['mes'] = df['data'].dt.month
df['dia_semana'] = df['data'].dt.day_name()
df['trimestre'] = df['data'].dt.quarter
print(df.head())
# Resample - agregar por período
df['valor'] = range(1, len(datas) + 1)
mensal = df.set_index('data')['valor'].resample('M').sum()
print(f"\nTotal por mês:\n{mensal}")
⚠️ Armadilhas Comuns e Como Evitá-las
1. Mutabilidade de datetime
import datetime
# CUIDADO: datetime é mutável!
dt = datetime.datetime(2026, 5, 13)
dt_modificado = dt.replace(month=12) # Cria novo objeto
print(f"Original: {dt}")
print(f"Modificado: {dt_modificado}")
# Para alterar, você precisa atribuir
dt = dt.replace(month=12)
print(f"Alterado: {dt}")
2. Fusos horários e localization
import datetime
import pytz
# Sempre especifique timezone
tz = pytz.timezone('America/Sao_Paulo')
dt = datetime.datetime(2026, 5, 13, 12, 0, tzinfo=tz)
print(f"Com timezone: {dt}")
# CUIDADO: localize, não apenas atribua
dt_nao_localizado = datetime.datetime(2026, 5, 13, 12, 0)
dt_localizado = tz.localize(dt_nao_localizado)
print(f"Localizado: {dt_localizado}")
# Usar timezone ao criar fromisoformat (Python 3.11+)
dt_iso = datetime.datetime.fromisoformat("2026-05-13T12:00:00-03:00")
print(f"From ISO: {dt_iso}")
3. Datas fora do intervalo válido
import datetime
# CUIDADO: datas inválidas podem raising erro ou gerar resultados inesperados
try:
dt = datetime.datetime(2026, 2, 30) # Fevereiro não tem 30 dias
except ValueError as e:
print(f"Erro: {e}")
# Sempre valide datas
def data_valida(ano, mes, dia):
try:
datetime.date(ano, mes, dia)
return True
except ValueError:
return False
print(f"2026-02-30 válida? {data_valida(2026, 2, 30)}")
print(f"2026-02-28 válida? {data_valida(2026, 2, 28)}")
print(f"2024-02-29 válida? {data_valida(2024, 2, 29)}") # Ano bissexto
🚀 Próximos Passos
Agora que você domina o módulo datetime do Python, você está preparado para lidar com a maioria das situações envolvendo datas e horas em suas aplicações. Para aprofundar ainda mais seu conhecimento, recomendamos:
- Strings em Python —-learn como formatar e manipular strings, complementando o trabalho com datas
- Tratamento de Erros — descubra como lidar com exceções que podem surgir ao trabalhar com datas inválidas
- Pandas para Análise de Dados — explore funcionalidades avançadas de séries temporais
- Curso Completo de Python — do zero ao avançado com projetos reais
O domínio de datetime é fundamental para qualquer desenvolvedor Python. Continue praticando e explorando as possibilidades deste módulo poderoso! 🎯