Preserve um valor de publicação que contém apenas a data, interpretando-o como uma data do calendário e mantendo essa data como referência. Se uma exportação exigir um carimbo de data/hora UTC, adote uma convenção explícita de meia-noite UTC. Este passo a passo no Terminal do Mac mostra a diferença e testa a conversão de ida e volta.

Decida o que o campo de publicação realmente significa

Suponha que uma lista de publicações contenha o valor sintético 2028-06-15. Sua tarefa é validar esse valor e prepará-lo para uma exportação sem exibir acidentalmente 14 de junho. Antes de escolher um analisador, decida se o campo registra um dia de publicação ou um momento específico da publicação.

Estes quatro conceitos têm funções diferentes:

Conceito Exemplo sintético Significado
Data civil 2028-06-15 Um dia do calendário, sem horário nem deslocamento UTC
Instante 2028-06-15T00:00:00+00:00 Um momento específico expresso em UTC
Deslocamento UTC +09:00 A diferença entre a hora local do relógio e o UTC
Fuso horário nomeado America/Los_Angeles Um identificador usado para obter as regras aplicáveis de fuso horário

A RFC 3339 define um full-date separadamente de um date-time; a gramática do carimbo de data/hora acrescenta uma hora e um deslocamento à data. Portanto, uma data de publicação isolada não contém as informações necessárias para identificar um instante de publicação. Escolher meia-noite acrescenta informações ausentes na entrada. RFC 3339, seção 5.6

Um fuso horário nomeado também contém mais informações do que um único deslocamento numérico. A documentação de zoneinfo do Python demonstra como um fuso pode usar deslocamentos diferentes durante a transição para o horário de verão. Para um rótulo que contém apenas a data, não é preciso resolver essas regras. Python: suporte a fusos horários IANA

Use esta regra de decisão antes de exportar:

  • O campo significa “publicado neste dia”: mantenha um valor que contenha apenas a data durante todo o armazenamento e a exibição.
  • Um formato de destino exige um carimbo de data/hora: mantenha a data e derive um suporte de meia-noite UTC segundo uma convenção documentada.
  • O campo significa “publicado neste momento”: obtenha a hora e o deslocamento reais, ou a hora e o fuso nomeado necessários para estabelecer esse momento.

A convenção de suporte é útil para compatibilidade, mas não recupera um horário de publicação desconhecido. Um nome de campo como utc_carrier deixa essa limitação visível; chamá-lo de published_at sugeriria informações que a fonte nunca forneceu.

Entenda como surge o erro do dia anterior

Considere dois possíveis fluxos de processamento para 2028-06-15. No primeiro, um programa inventa meia-noite no deslocamento fixo +09:00 e, em seguida, converte esse instante para UTC. O resultado é 2028-06-14T15:00:00+00:00: subtrair nove horas cruza a fronteira do dia.

No segundo fluxo, o programa cria intencionalmente meia-noite UTC: 2028-06-15T00:00:00+00:00. Exibir esse mesmo instante no deslocamento fixo -07:00 produz 2028-06-14T17:00:00-07:00. Esses são cálculos ilustrativos de deslocamento, não afirmações sobre o deslocamento de um fuso nomeado nessa data.

Ambos os cálculos preservam seus respectivos instantes. Nenhum deles preserva o rótulo original do calendário em todos os fusos de exibição. O Python documenta que astimezone() ajusta os campos do relógio enquanto preserva o horário UTC representado. Python: datetime.astimezone()

A consequência prática é que a análise e a exibição precisam seguir um contrato comum. Se uma data foi colocada em um suporte de meia-noite UTC, recupere seus campos de calendário em UTC. Se quiser que o rótulo de publicação permaneça inalterado onde quer que alguém abra a exportação, exiba a data civil retida.

Não suponha que todas as linguagens forneçam as mesmas informações ausentes. O ECMAScript especifica que formatos de data sem deslocamento contêm apenas a data e são interpretados como UTC, enquanto formatos de data e hora sem deslocamento são interpretados como horário local. Portanto, acrescentar T00:00:00 a uma string pode mudar sua interpretação em JavaScript. ECMAScript: Date.parse

Execute uma verificação completa da data de publicação no Terminal do Mac

Este passo a passo valida três datas sintéticas, imprime uma prévia separada por tabulações e testa a rejeição de entradas malformadas. Ele não modifica uma lista de publicações nem cria um arquivo de exportação.

No Finder, abra /Applications/Utilities e clique duas vezes em Terminal. A Apple documenta esse método como uma forma compatível de abrir o aplicativo de linha de comando. Apple: abrir ou encerrar o Terminal no Mac

Execute o comando a seguir para verificar seu interpretador:

python3 --version

Use o Python 3.11 ou posterior neste passo a passo. Se python3 não estiver disponível ou informar uma versão mais antiga, siga as instruções oficiais de instalação para macOS antes de continuar. Em seguida, reabra o Terminal e confira novamente. O Python documenta tanto seu instalador para macOS quanto a execução de scripts com python3. Python: usando Python no macOS

Cole o bloco inteiro abaixo, incluindo o PY final, e pressione Return. O argumento - instrui o Python a ler o programa da entrada padrão. Todos os dados de exemplo e as importações estão incluídos. Python: linha de comando e ambiente

python3 - <<'PY'
import re
from datetime import date, datetime, time, timezone


def parse_publication_date(text):
    if not isinstance(text, str) or re.fullmatch(
        r"[0-9]{4}-[0-9]{2}-[0-9]{2}", text
    ) is None:
        raise ValueError("Expected YYYY-MM-DD")
    return date.fromisoformat(text)


def utc_carrier(day):
    return datetime.combine(day, time(0), tzinfo=timezone.utc)


samples = ["2028-02-29", "2028-06-15", "2028-12-31"]
parsed = [(text, parse_publication_date(text)) for text in samples]

print("publication_date\tutc_carrier")
for original, day in parsed:
    carrier = utc_carrier(day)
    assert day.isoformat() == original
    assert carrier.astimezone(timezone.utc).date() == day
    print(day.isoformat(), carrier.isoformat(timespec="seconds"), sep="\t")

for invalid in [
    "2027-02-29",
    "2028-6-15",
    "2028-06-15T00:00:00",
    " 2028-06-15",
]:
    try:
        parse_publication_date(invalid)
    except ValueError:
        pass
    else:
        raise AssertionError(f"Unexpected acceptance: {invalid!r}")

print("Round-trip and rejection checks passed.")
PY

A saída esperada é:

publication_date	utc_carrier
2028-02-29	2028-02-29T00:00:00+00:00
2028-06-15	2028-06-15T00:00:00+00:00
2028-12-31	2028-12-31T00:00:00+00:00
Round-trip and rejection checks passed.

O exemplo e os dois cálculos de deslocamento fixo foram executados com sucesso usando o interpretador Python disponível. As instruções específicas para Mac, sobre como abrir o Terminal e verificar o interpretador, seguem a documentação oficial vinculada.

Por que o exemplo preserva o dia de publicação

O analisador verifica separadamente duas coisas: o formato exato da string e a validade da data no calendário. Sua expressão regular exige quatro dígitos para o ano, dois para o mês e dois para o dia. Em seguida, o analisador de datas rejeita datas impossíveis. Isso impede que uma coluna de publicação aceite silenciosamente carimbos de data/hora, espaços ao redor ou entradas abreviadas.

Essa verificação explícita do formato é importante porque date.fromisoformat() também aceita outras representações ISO, incluindo datas compactas e datas semanais. datetime.combine() então adiciona deliberadamente meia-noite e UTC. Python: tipos básicos de data e hora

O programa analisa a lista de amostras inteira antes de imprimir o cabeçalho. Se você substituir uma amostra por um valor inválido, a execução será interrompida antes que qualquer linha da prévia apareça. As verificações deliberadas de entrada inválida no final são testes separados; suas exceções esperadas são capturadas para que todos os casos de rejeição possam ser verificados.

Duas asserções de conversão de ida e volta expressam o contrato. A primeira verifica se a análise e a formatação da data reproduzem o rótulo original. A segunda verifica se o suporte derivado fornece a mesma data quando interpretado em UTC. Juntas, elas verificam a tarefa exata de preservação, em vez de apenas verificar se algum carimbo de data/hora pode ser produzido.

A saída usa explicitamente +00:00. A RFC 3339 também permite Z como designador do deslocamento UTC, mas acrescentar qualquer um desses sufixos a uma data isolada não fornece o componente de hora ausente. Mantenha o formato que contém apenas a data ou crie o carimbo de data/hora completo intencionalmente. RFC 3339, seção 5.6

Diagnostique uma exportação que ainda altera a data

Se uma prévia posterior mostrar o dia anterior, inspecione os valores em cada etapa. Use a amostra sintética do meio, 2028-06-15, para comparar cada etapa com um rótulo conhecido.

Ponto de verificação Esperado segundo a convenção de suporte O que uma diferença sugere
Campo original de publicação 2028-06-15 A entrada mudou antes da análise
Data analisada, exibida como texto 2028-06-15 A análise ou a normalização alterou o rótulo
Suporte UTC derivado 2028-06-15T00:00:00+00:00 Foi introduzido outro horário ou deslocamento
Data recuperada em UTC 2028-06-15 A conversão ou extração usou o contrato errado
Rótulo de publicação exibido ao leitor 2028-06-15 O visualizador pode estar exibindo o suporte em outro fuso

Verifique o exibidor independentemente do analisador. Um suporte UTC correto ainda pode produzir outro dia do calendário quando é exibido usando uma configuração de fuso local. Para um rótulo de publicação, forneça ao exibidor a data retida que contém apenas a data. Se ele aceitar apenas carimbos de data/hora, use uma opção documentada de exibição em UTC e verifique o resultado.

Se a ferramenta de destino aceitar apenas instantes e sempre os exibir no horário local, a convenção de meia-noite UTC não pode garantir um rótulo de data inalterado. Preserve uma coluna de texto separada que contenha apenas a data, use um campo compatível que contenha apenas a data ou escolha um exibidor com formatação UTC explícita. A limitação decorre dos cálculos de deslocamento acima; mudar apenas o analisador não a elimina.

Evite também tratar um carimbo de data/hora existente como se fosse uma entrada que contém apenas a data. Para um instante real, alterar o fuso significa convertê-lo. O Python distingue essa operação de substituir tzinfo, o que associa informações de fuso sem ajustar os campos do relógio. Python: comportamento da conversão de fuso horário

Para sua lista de publicações, mantenha publication_date como o valor de calendário de referência. Derive um suporte UTC somente em uma interface que o exija, associe a convenção ao campo e verifique a extração em UTC antes de confiar na prévia. Assim, você terá um método reproduzível para preservar o dia fornecido sem inventar um momento de publicação.

Fontes