Skip to content

Python Datetime: Guia Completo de Datas e Horas em Python

Updated on

Trabalhar com datas e horas em Python deveria ser simples, mas raramente é. Você precisa fazer parsing de uma string de data de um arquivo CSV, mas "01/02/2026" pode significar 2 de janeiro ou 1 de fevereiro dependendo da localidade. Você quer calcular a diferença entre dois timestamps, mas um é uma string e o outro é uma época Unix. Você confunde strftime e strptime pela décima vez neste mês. Operações de data e hora são uma fonte constante de bugs, erros de deslocamento e dores de cabeça com fusos horários em código de produção.

As consequências vão além do incômodo. Um formato de data errado em um relatório financeiro significa cálculos incorretos. Uma comparação naive de datetime que ignora fusos horários causa jobs cron duplicados. Um cálculo errado de timedelta cobra de um cliente 31 dias em vez de 30.

O módulo integrado datetime do Python resolve esses problemas com uma API limpa e consistente. Ele fornece classes para datas, horas, timestamps e durações. Uma vez que você aprende seus padrões -- e especialmente a diferença entre strftime e strptime -- você pode lidar com qualquer operação de data sem bibliotecas de terceiros.

📚

Obtendo a Data e Hora Atuais

O ponto de partida mais comum é obter a data e hora atuais. O módulo datetime oferece várias formas de fazer isso.

from datetime import datetime, date
 
# Data e hora atuais
now = datetime.now()
print(now)           # 2026-02-10 14:30:45.123456
 
# Apenas data atual
today = date.today()
print(today)         # 2026-02-10
 
# datetime.today() é similar a datetime.now() mas sem suporte a fuso horário
now_alt = datetime.today()
print(now_alt)       # 2026-02-10 14:30:45.123456

A diferença entre datetime.now() e datetime.today() é sutil mas importante. datetime.now() aceita um parâmetro opcional tz para datetimes com fuso horário. datetime.today() não. Para a maioria do código, prefira datetime.now().

from datetime import datetime
from zoneinfo import ZoneInfo
 
# Hora atual com fuso horário
utc_now = datetime.now(tz=ZoneInfo("UTC"))
print(utc_now)  # 2026-02-10 14:30:45.123456+00:00
 
tokyo_now = datetime.now(tz=ZoneInfo("Asia/Tokyo"))
print(tokyo_now)  # 2026-02-10 23:30:45.123456+09:00

Criando Objetos Datetime

Você pode criar objetos datetime a partir de componentes individuais ou de dados existentes.

from datetime import datetime, date, time
 
# A partir de ano, mês, dia, hora, minuto, segundo
dt = datetime(2026, 3, 15, 9, 30, 0)
print(dt)  # 2026-03-15 09:30:00
 
# Apenas data
d = date(2026, 12, 25)
print(d)  # 2026-12-25
 
# Apenas hora
t = time(14, 30, 0)
print(t)  # 14:30:00
 
# Combinar data e hora
combined = datetime.combine(d, t)
print(combined)  # 2026-12-25 14:30:00

Você também pode extrair componentes de um datetime existente.

from datetime import datetime
 
dt = datetime(2026, 3, 15, 9, 30, 45)
 
print(dt.year)        # 2026
print(dt.month)       # 3
print(dt.day)         # 15
print(dt.hour)        # 9
print(dt.minute)      # 30
print(dt.second)      # 45
print(dt.weekday())   # 6 (Domingo, Segunda=0)
print(dt.isoformat()) # 2026-03-15T09:30:45

Formatando Datas com strftime

strftime significa "string format time" (formatar string de tempo). Ele converte um objeto datetime em uma string formatada. Você passa uma string de formato com diretivas que são substituídas por componentes de data.

from datetime import datetime
 
dt = datetime(2026, 3, 15, 9, 5, 7)
 
# Formatos comuns
print(dt.strftime("%Y-%m-%d"))              # 2026-03-15
print(dt.strftime("%d/%m/%Y"))              # 15/03/2026
print(dt.strftime("%B %d, %Y"))             # March 15, 2026
print(dt.strftime("%Y-%m-%d %H:%M:%S"))     # 2026-03-15 09:05:07
print(dt.strftime("%I:%M %p"))              # 09:05 AM
print(dt.strftime("%A, %B %d, %Y"))         # Sunday, March 15, 2026

Uma forma rápida de lembrar: strftime = string from time (datetime para string).

Referência de Códigos de Formato strftime

CódigoSignificadoExemplo
%YAno com 4 dígitos2026
%yAno com 2 dígitos26
%mMês com zero à esquerda03
%BNome completo do mêsMarch
%bNome abreviado do mêsMar
%dDia do mês (com zero)15
%ANome completo do dia da semanaSunday
%aNome abreviado do dia da semanaSun
%HHora (24h, com zero)09
%IHora (12h, com zero)09
%MMinuto (com zero)05
%SSegundo (com zero)07
%pAM/PMAM
%fMicrossegundo (6 dígitos com zero)000000
%zDeslocamento UTC (+HHMM ou -HHMM)+0000
%ZNome do fuso horárioUTC
%jDia do ano (001-366)074
%%Caractere literal %%

Padrões de Formato Mais Usados

PadrãoString de FormatoSaída
ISO 8601%Y-%m-%dT%H:%M:%S2026-03-15T09:05:07
Data EUA%m/%d/%Y03/15/2026
Data europeia%d/%m/%Y15/03/2026
Data legível%B %d, %YMarch 15, 2026
Timestamp de log%Y-%m-%d %H:%M:%S2026-03-15 09:05:07
Hora 12h%I:%M:%S %p09:05:07 AM
Data compacta%Y%m%d20260315
Timestamp seguro para arquivo%Y%m%d_%H%M%S20260315_090507

Parsing de Strings com strptime

strptime significa "string parse time" (fazer parsing de string de tempo). É o inverso de strftime -- converte uma string em um objeto datetime. Você fornece a string e o formato que ela segue.

from datetime import datetime
 
# Fazer parsing de vários formatos de string de data
dt1 = datetime.strptime("2026-03-15", "%Y-%m-%d")
print(dt1)  # 2026-03-15 00:00:00
 
dt2 = datetime.strptime("15/03/2026", "%d/%m/%Y")
print(dt2)  # 2026-03-15 00:00:00
 
dt3 = datetime.strptime("March 15, 2026 09:30 AM", "%B %d, %Y %I:%M %p")
print(dt3)  # 2026-03-15 09:30:00
 
dt4 = datetime.strptime("2026-03-15T09:30:00", "%Y-%m-%dT%H:%M:%S")
print(dt4)  # 2026-03-15 09:30:00

Lembre-se: strptime = string parse time (string para datetime).

Tratando Erros de Parsing

Se a string não corresponder ao formato, Python levanta um ValueError. Sempre envolva chamadas strptime em tratamento de erros ao fazer parsing de entrada do usuário ou dados externos.

from datetime import datetime
 
def safe_parse_date(date_string, fmt="%Y-%m-%d"):
    """Parse a date string safely, returning None on failure."""
    try:
        return datetime.strptime(date_string, fmt)
    except ValueError as e:
        print(f"Could not parse '{date_string}': {e}")
        return None
 
# Valid input
print(safe_parse_date("2026-03-15"))       # 2026-03-15 00:00:00
 
# Invalid input
print(safe_parse_date("15-03-2026"))       # Could not parse '15-03-2026': ...
print(safe_parse_date("not a date"))       # Could not parse 'not a date': ...

Parsing de Múltiplos Formatos

Quando você recebe datas em formatos imprevisíveis, tente múltiplos padrões.

from datetime import datetime
 
def parse_flexible_date(date_string):
    """Try multiple date formats and return the first match."""
    formats = [
        "%Y-%m-%d",
        "%d/%m/%Y",
        "%m/%d/%Y",
        "%B %d, %Y",
        "%b %d, %Y",
        "%Y-%m-%dT%H:%M:%S",
        "%Y-%m-%d %H:%M:%S",
    ]
    for fmt in formats:
        try:
            return datetime.strptime(date_string, fmt)
        except ValueError:
            continue
    raise ValueError(f"No matching format found for '{date_string}'")
 
print(parse_flexible_date("2026-03-15"))         # 2026-03-15 00:00:00
print(parse_flexible_date("March 15, 2026"))     # 2026-03-15 00:00:00
print(parse_flexible_date("15/03/2026"))         # 2026-03-15 00:00:00

Aritmética de Datas com timedelta

A classe timedelta representa uma duração -- a diferença entre duas datas ou horas. Você pode adicionar ou subtrair objetos timedelta para mover datas para frente ou para trás.

from datetime import datetime, timedelta
 
now = datetime(2026, 2, 10, 12, 0, 0)
 
# Adicionar dias
tomorrow = now + timedelta(days=1)
print(tomorrow)  # 2026-02-11 12:00:00
 
# Subtrair dias
last_week = now - timedelta(weeks=1)
print(last_week)  # 2026-02-03 12:00:00
 
# Adicionar horas e minutos
later = now + timedelta(hours=5, minutes=30)
print(later)  # 2026-02-10 17:30:00
 
# Combinar múltiplas unidades
future = now + timedelta(weeks=2, days=3, hours=6)
print(future)  # 2026-02-27 18:00:00

Calculando Diferenças de Tempo

Subtrair um datetime de outro retorna um timedelta.

from datetime import datetime
 
start = datetime(2026, 1, 1)
end = datetime(2026, 12, 31)
 
diff = end - start
print(diff)              # 364 days, 0:00:00
print(diff.days)         # 364
print(diff.total_seconds())  # 31449600.0

Parâmetros do Construtor timedelta

ParâmetroDescriçãoExemplo
weeksNúmero de semanastimedelta(weeks=2) = 14 dias
daysNúmero de diastimedelta(days=30)
hoursNúmero de horastimedelta(hours=12)
minutesNúmero de minutostimedelta(minutes=45)
secondsNúmero de segundostimedelta(seconds=120)
millisecondsNúmero de milissegundostimedelta(milliseconds=500)
microsecondsNúmero de microssegundostimedelta(microseconds=1000)

Todos os parâmetros podem ser combinados. Internamente, timedelta armazena apenas days, seconds e microseconds. Todo o resto é convertido.

from datetime import timedelta
 
delta = timedelta(weeks=1, days=2, hours=3, minutes=30, seconds=45)
print(delta)                    # 9 days, 3:30:45
print(delta.days)               # 9
print(delta.seconds)            # 12645 (3*3600 + 30*60 + 45)
print(delta.total_seconds())    # 790245.0

Comparando Datas

Objetos datetime suportam todos os operadores de comparação padrão. Isso torna a ordenação e filtragem de datas simples.

from datetime import datetime
 
dt1 = datetime(2026, 1, 1)
dt2 = datetime(2026, 6, 15)
dt3 = datetime(2026, 12, 31)
 
print(dt1 < dt2)    # True
print(dt3 > dt2)    # True
print(dt1 == dt2)   # False
print(dt1 != dt2)   # True

Ordenando Datas

from datetime import datetime
 
dates = [
    datetime(2026, 12, 25),
    datetime(2026, 1, 1),
    datetime(2026, 7, 4),
    datetime(2026, 2, 14),
]
 
sorted_dates = sorted(dates)
for d in sorted_dates:
    print(d.strftime("%B %d, %Y"))
 
# January 01, 2026
# February 14, 2026
# July 04, 2026
# December 25, 2026

Trabalhando com Timestamps

Timestamps Unix representam segundos desde 1 de janeiro de 1970 (a época Unix). O módulo datetime pode converter entre timestamps e objetos datetime.

from datetime import datetime, timezone
 
# Datetime para timestamp
dt = datetime(2026, 3, 15, 9, 30, 0)
ts = dt.timestamp()
print(ts)  # 1773814200.0 (depende do fuso horário local)
 
# Timestamp para datetime (com fuso horário, recomendado)
dt_aware = datetime.fromtimestamp(ts, tz=timezone.utc)
print(dt_aware)  # 2026-03-15 01:30:00+00:00

Importante: datetime.fromtimestamp() sem fuso horário retorna a hora local. Para UTC, sempre passe tz=timezone.utc.

Tratamento de Fusos Horários

Datetimes ingênuos (sem informação de fuso horário) são uma fonte comum de bugs. Python fornece duas abordagens integradas para datetimes com fuso horário.

Usando datetime.timezone (Integrado)

A classe timezone lida com deslocamentos UTC fixos.

from datetime import datetime, timezone, timedelta
 
# UTC
utc_now = datetime.now(timezone.utc)
print(utc_now)  # 2026-02-10 14:30:00+00:00
 
# Deslocamento fixo (ex: UTC+5:30 para Índia)
ist = timezone(timedelta(hours=5, minutes=30))
india_time = datetime.now(ist)
print(india_time)  # 2026-02-10 20:00:00+05:30
 
# Converter entre fusos horários
utc_time = datetime(2026, 3, 15, 12, 0, 0, tzinfo=timezone.utc)
eastern = timezone(timedelta(hours=-5))
eastern_time = utc_time.astimezone(eastern)
print(eastern_time)  # 2026-03-15 07:00:00-05:00

Usando zoneinfo (Python 3.9+)

Para fusos horários nomeados com tratamento correto de horário de verão, use o módulo zoneinfo.

from datetime import datetime
from zoneinfo import ZoneInfo
 
# Fusos horários nomeados
utc = ZoneInfo("UTC")
eastern = ZoneInfo("America/New_York")
tokyo = ZoneInfo("Asia/Tokyo")
 
# Criar datetime com fuso horário
dt = datetime(2026, 7, 15, 12, 0, 0, tzinfo=utc)
print(dt)  # 2026-07-15 12:00:00+00:00
 
# Converter para outros fusos horários
print(dt.astimezone(eastern))  # 2026-07-15 08:00:00-04:00 (EDT)
print(dt.astimezone(tokyo))    # 2026-07-15 21:00:00+09:00

Datetimes Ingênuos vs Conscientes

CaracterísticaIngênuoConsciente
Tem informação de fuso horárioNãoSim
Seguro para comparações entre zonasNãoSim
Criado por datetime.now()SimNão (a menos que tz seja passado)
Pode ser misturado em aritméticaApenas com outros ingênuosApenas com outros conscientes
Recomendado para produçãoNãoSim

Você não pode comparar ou subtrair um datetime ingênuo de um consciente. Python levanta um TypeError.

Exemplos Práticos

Calcular a Idade de uma Pessoa

from datetime import date
 
def calculate_age(birth_date):
    """Calculate age in years from a birth date."""
    today = date.today()
    age = today.year - birth_date.year
    if (today.month, today.day) < (birth_date.month, birth_date.day):
        age -= 1
    return age
 
birthday = date(1995, 8, 20)
print(f"Age: {calculate_age(birthday)} years")  # Age: 30 years (as of Feb 2026)

Gerar um Intervalo de Datas

from datetime import date, timedelta
 
def date_range(start, end, step_days=1):
    """Generate dates from start to end (inclusive)."""
    current = start
    while current <= end:
        yield current
        current += timedelta(days=step_days)
 
start = date(2026, 2, 1)
end = date(2026, 2, 7)
 
for d in date_range(start, end):
    print(d.strftime("%A, %B %d"))

Contar Dias Úteis Entre Duas Datas

from datetime import date, timedelta
 
def business_days_between(start, end):
    """Count weekdays (Mon-Fri) between two dates, excluding endpoints."""
    count = 0
    current = start + timedelta(days=1)
    while current < end:
        if current.weekday() < 5:  # 0=Mon, 4=Fri
            count += 1
        current += timedelta(days=1)
    return count
 
start = date(2026, 2, 1)
end = date(2026, 2, 28)
print(f"Business days: {business_days_between(start, end)}")  # Business days: 19

Experimentando com Datetime no Jupyter

Operações de data e hora se beneficiam de experimentação interativa. Quando você está fazendo parsing de formatos de data inconsistentes de um CSV ou depurando conversões de fuso horário, poder testar cada passo em uma célula de notebook economiza tempo significativo.

RunCell (opens in a new tab) é um agente de IA que trabalha diretamente dentro de notebooks Jupyter. Ele pode inspecionar seus objetos datetime, sugerir os códigos de formato strftime/strptime corretos para seus dados e ajudar a depurar problemas de conversão de fuso horário em tempo real.

strftime vs strptime: Comparação Rápida

strftimestrptime
Nome completoString Format TimeString Parse Time
Direçãodatetime -> stringstring -> datetime
Chamado emUm objeto datetimeA classe datetime
Sintaxedt.strftime("%Y-%m-%d")datetime.strptime(s, "%Y-%m-%d")
RetornaUma string formatadaUm objeto datetime
LevantaNuncaValueError se o formato não corresponder
Caso de usoExibição, logging, nomes de arquivoParsing de CSV, respostas API, entrada do usuário
from datetime import datetime
 
# strftime: datetime -> string
dt = datetime(2026, 3, 15, 9, 30)
formatted = dt.strftime("%B %d, %Y at %I:%M %p")
print(formatted)  # March 15, 2026 at 09:30 AM
 
# strptime: string -> datetime
parsed = datetime.strptime("March 15, 2026 at 09:30 AM", "%B %d, %Y at %I:%M %p")
print(parsed)  # 2026-03-15 09:30:00

FAQ

Como obter a data e hora atuais em Python?

Use datetime.now() do módulo datetime. Para apenas a data, use date.today(). Para a hora atual com fuso horário, passe um fuso: datetime.now(tz=timezone.utc). Essas são as abordagens padrão e não requerem bibliotecas de terceiros.

Qual é a diferença entre strftime e strptime em Python?

strftime converte um objeto datetime em uma string formatada (string from time). strptime faz parsing de uma string e a converte em um objeto datetime (string parse time). Pense assim: strftime produz strings, strptime consome strings. Ambos usam os mesmos códigos de formato como %Y, %m, %d.

Como adicionar dias a uma data em Python?

Use a classe timedelta. Importe-a de datetime, depois adicione à sua data: new_date = old_date + timedelta(days=7). Você também pode usar weeks, hours, minutes e seconds como parâmetros. Subtrair funciona da mesma forma: past_date = today - timedelta(days=30).

Como converter uma string em datetime em Python?

Use datetime.strptime(string, format). Você precisa fornecer uma string de formato que corresponda à sua entrada. Por exemplo, datetime.strptime("2026-03-15", "%Y-%m-%d") faz parsing de uma data ISO. Se a string não corresponder ao formato, Python levanta um ValueError, então envolva a chamada em um bloco try/except para dados externos.

Como lidar com fusos horários em Python datetime?

Para Python 3.9+, use o módulo integrado zoneinfo: from zoneinfo import ZoneInfo. Crie datetimes com fuso horário com datetime.now(tz=ZoneInfo("UTC")) e converta entre zonas com dt.astimezone(ZoneInfo("America/New_York")). Para deslocamentos UTC fixos, use datetime.timezone(timedelta(hours=N)). Evite datetimes ingênuos em código de produção.

Conclusão

O módulo datetime do Python fornece tudo que você precisa para operações de data e hora: criar datas, formatá-las para exibição, fazer parsing de strings, realizar aritmética e lidar com fusos horários. Os padrões-chave são consistentes e previsíveis uma vez aprendidos.

Lembre-se da distinção central: strftime formata um datetime em uma string, strptime faz parsing de uma string em um datetime. Use timedelta para aritmética de datas. Use zoneinfo (Python 3.9+) para tratamento correto de fusos horários. Mantenha datetimes com fuso horário em código de produção para evitar bugs sutis de comparação.

Para a maioria dos projetos, o módulo integrado datetime é suficiente. Você não precisa de pytz em Python moderno -- zoneinfo lida com fusos horários nomeados nativamente. Comece com datetime.now(tz=timezone.utc) como ponto de referência e converta para fusos horários locais apenas ao exibir para usuários.

📚