Curso de Python / Trabalhar com datas, horas e fusos horários
Use date para representar um dia do calendário e datetime com zoneinfo quando a hora e o fuso forem relevantes. Um horário sem fuso conhecido não identifica necessariamente um instante; defina o que os dados significam antes de armazenar ou converter valores.
Distinguir data, duração e instante
date contém ano, mês e dia. datetime combina data e hora, enquanto timedelta representa uma duração. Uma data de vencimento pode ser apenas um dia do calendário; o instante de uma transferência exige uma referência temporal mais precisa. Transformar toda data em meia-noite pode introduzir uma informação que não existia no dado original.
Um datetime naive não possui informações suficientes de fuso; um valor aware possui informações de deslocamento que permitem situá-lo em relação a outros horários. Por exemplo, 09:00 em Seul e 09:00 em UTC não indicam o mesmo instante. UTC é a referência de Tempo Universal Coordenado; o deslocamento +09:00 significa nove horas à frente dela.
date.fromisoformat interpreta uma data como 2026-10-17 e rejeita dias inexistentes com ValueError. Somar sete dias com timedelta(days=7) é diferente de avançar um mês: os meses têm durações diferentes, e a aplicação precisa decidir como tratar uma data como 31 de janeiro ao mudar de mês.
A documentação de datetime: datas, horas e durações detalha essas classes e a distinção entre valores naive e aware.
Converter um instante UTC para o horário de Seul
Use Python 3.9 ou posterior, pois zoneinfo faz parte da biblioteca padrão a partir dessa versão. Crie uma pasta de prática, selecione o ambiente virtual do projeto e salve o código completo abaixo como dates.py, em UTF-8. O exemplo não recebe a data atual: ele usa 17 de outubro de 2026 como valor fixo para tornar o resultado reproduzível.
ZoneInfo consulta regras de fusos da base IANA, uma coleção de identificadores e regras de horários regionais. Se o sistema não fornecer essa base, algo comum no Windows, instale o pacote oficial tzdata no ambiente virtual selecionado com python -m pip install tzdata. Se ocorrer ZoneInfoNotFoundError, confira se a instalação e a execução usam o mesmo interpretador. O pacote fornece dados de fuso; o módulo zoneinfo já vem com Python.
from datetime import date, datetime, timedelta, timezone
from zoneinfo import ZoneInfo
day = date.fromisoformat("2026-10-17")
print(day + timedelta(days=7))
utc = datetime(2026, 10, 17, 0, 0, tzinfo=timezone.utc)
seoul = utc.astimezone(ZoneInfo("Asia/Seoul"))
print(utc.isoformat())
print(seoul.isoformat())
Execute python dates.py no terminal da pasta. Fora de um ambiente virtual no macOS ou Ubuntu, o comando pode se chamar python3. O resultado esperado é:
2026-10-24
2026-10-17T00:00:00+00:00
2026-10-17T09:00:00+09:00
A primeira linha soma sete dias à data. As duas seguintes representam o mesmo instante: meia-noite em UTC equivale a 09:00 em Seul nessa data. isoformat() inclui o deslocamento nos valores aware, enquanto a data simples não recebe hora nem fuso.
Comparar astimezone com replace
astimezone preserva o instante e muda sua representação no fuso de destino. Já replace(tzinfo=...) mantém os números do relógio e atribui outra interpretação de fuso. Essa atribuição só faz sentido quando você sabe que os campos originais pertencem ao fuso informado; ela não substitui uma conversão.
Salve este segundo programa completo como zones.py, na mesma pasta, e execute python zones.py. Use o mesmo ambiente com os dados de fuso disponíveis.
from datetime import datetime, timezone
from zoneinfo import ZoneInfo
utc = datetime(2026, 10, 17, 0, 0, tzinfo=timezone.utc)
print(utc.astimezone(ZoneInfo("Asia/Seoul")).isoformat())
print(utc.replace(tzinfo=ZoneInfo("Asia/Seoul")).isoformat())
try:
print(datetime(2026, 10, 17) - utc)
except TypeError:
print("naive and aware cannot be subtracted")
Resultado esperado:
2026-10-17T09:00:00+09:00
2026-10-17T00:00:00+09:00
naive and aware cannot be subtracted
O primeiro horário mostra a conversão correta para 09:00. O segundo conserva 00:00, agora com deslocamento +09:00, e representa um instante nove horas anterior ao original. A última linha é uma mensagem didática em inglês emitida pelo próprio programa após capturar TypeError: não é possível subtrair diretamente um datetime naive de um aware.
Acrescentar UTC a um horário de origem desconhecida pode esconder o erro sem recuperar a informação ausente. Descubra primeiro o fuso na documentação da API, na configuração de origem ou no contrato dos dados. Os identificadores regionais, como Asia/Seoul, usam regras históricas; um deslocamento fixo não substitui todas as regras de um fuso regional.
Veja as fontes de dados e condições de uso de zoneinfo. A aplicação deve manter a base de fusos atualizada, porque regras locais podem mudar.
Definir o armazenamento e verificar limites
Para registrar instantes de transações, uma opção é armazenar valores em UTC e convertê-los para o fuso do usuário na apresentação. Se o fuso regional original tiver significado para a operação, guarde também seu identificador: uma string ISO com deslocamento numérico não preserva, por si só, o nome da região nem suas regras futuras. Para uma despesa cujo significado seja apenas “dia 17”, prefira conservar a data, sem inventar um instante.
- Em
dates.py, altere apenas a hora da construção deutcde0para23. A data calculada na primeira linha continua igual; a última linha passa a2026-10-18T08:00:00+09:00, no dia seguinte em Seul. - Restaure a hora para
0e execute novamente para recuperar a saída original. - Troque a entrada de
date.fromisoformatpor2026-02-30. O programa deve parar comValueErrorantes de imprimir resultados. Em um formulário real, capture esse erro e peça uma data válida; depois restaure a entrada de outubro. - Compare as duas primeiras linhas de
zones.pye explique por que converter o instante é diferente de atribuir um fuso aos mesmos campos. Mantenha a diferença entre data de negócio e instante nos filtros, no armazenamento e nos relatórios.




