Para formatar um instante de publicação em outro fuso horário, mantenha o instante original e informe o fuso de destino ao formatador. Este guia do Terminal do Mac gera um rótulo de publicação legível sem analisar o texto exibido nem adicionar horas manualmente.

De quais informações você precisa antes de converter?

Suponha que você esteja preparando um documento no Mac e receba o carimbo de data/hora sintético 2025-07-15T00:30:00Z. Você precisa da data e hora da publicação conforme exibidas em America/Los_Angeles. A tarefa é descrever esse mesmo momento usando a data do calendário e a hora local do destino.

Quatro termos determinam se você tem informações suficientes:

Termo Exemplo sintético Significado para esta tarefa
Data civil 2025-07-15 Um dia do calendário, sem hora nem fuso
Instante O momento representado por 2025-07-15T00:30:00Z O ponto no tempo que você preserva
Deslocamento UTC -07:00 A diferença entre a hora local e o UTC em um instante específico
Fuso horário nomeado America/Los_Angeles Regras usadas para determinar o deslocamento aplicável

A RFC 3339 define carimbos de data/hora que contêm data completa, hora e deslocamento UTC. A RFC 9557 explica a distinção adicional: um fuso nomeado fornece regras que mapeiam um instante para um deslocamento, enquanto o deslocamento numérico de um carimbo de data/hora, por si só, não descreve como o deslocamento de um local se comporta em outros momentos. RFC 3339, Seção 5.6, RFC 9557, Seção 1.2.

Use esta decisão sobre a entrada antes de fazer qualquer conversão:

  • Você já tem um Date do Foundation: passe-o diretamente a um formatador configurado para o fuso de destino.
  • Você tem um carimbo de data/hora com Z ou um deslocamento numérico explícito: analise esse carimbo original uma vez e, em seguida, formate o instante resultante.
  • Você tem apenas uma data civil: preserve-a como data, a menos que a tarefa forneça explicitamente uma hora e um fuso.
  • Você tem uma data e hora locais sem deslocamento: obtenha o fuso de origem e resolva qualquer ambiguidade antes de tratá-las como um instante.

Por exemplo, 2025-07-15 não permite saber se a publicação ocorreu antes ou depois da meia-noite em outro fuso. Atribuir meia-noite introduziria uma suposição. Da mesma forma, uma leitura do relógio local pode corresponder a zero ou a vários instantes durante uma transição de deslocamento; a RFC 9557 documenta esse limite. Converter um instante já estabelecido evita esse problema de mapeamento inverso. RFC 9557, Seção 1.2.

Por que você deve evitar analisar novamente o texto exibido?

A Apple define o Date do Foundation como um ponto específico no tempo, independente de qualquer calendário ou fuso horário. Seu valor não precisa se tornar outro Date para aparecer em outro fuso. A formatação fornece o calendário e o fuso necessários para produzir o texto. Date.

Um rótulo exibido pode omitir informações. Se você formatar um instante como uma data sem hora e depois analisar esse rótulo, não será possível recuperar do rótulo a hora que foi omitida. A documentação de formatação da Apple demonstra uma conversão de ida e volta somente com a data que reconstrói a meia-noite. Isso é útil quando meia-noite é o resultado pretendido, mas não preserva um instante de publicação arbitrário. Date.FormatStyle.

Mantenha esta ordem de operações:

  1. Leia o carimbo de data/hora original ou obtenha o Date existente.
  2. Mantenha esse instante como valor de trabalho.
  3. Escolha o fuso de destino, o calendário e a localidade de exibição.
  4. Formate o instante preservado no rótulo final.

Adicionar manualmente um deslocamento também altera a tarefa. A Apple documenta addingTimeInterval(_:) como a criação de uma nova data pela adição de tempo decorrido. Portanto, adicionar sete horas produz outro instante; escolher o fuso do formatador altera a representação do instante original. Date.

Execute um exemplo completo de horário de publicação no Mac

O exemplo requer macOS 12 ou posterior, no qual a API Date.FormatStyle da Apple está disponível, e uma cadeia de ferramentas Swift funcional. Ele usa o Foundation, sem pacotes adicionais. Date.FormatStyle.

Abra o Terminal e confira a cadeia de ferramentas:

swift --version

Se precisar das ferramentas de linha de comando da Apple, execute o comando a seguir e conclua a caixa de diálogo de instalação. A Apple documenta esse método de instalação e observa que uma instalação completa do Xcode já inclui as ferramentas de linha de comando. Em seguida, repita a verificação da versão. Instalar as ferramentas de linha de comando.

xcode-select --install

No TextEdit, crie um novo documento e escolha Formatar > Converter em Texto Simples. Cole o programa Swift completo abaixo e salve-o na Mesa com o nome publication-time.swift. Verifique se o nome do arquivo resultante termina em .swift, sem a extensão .txt adicionada. O guia do TextEdit da Apple documenta como criar, converter e salvar documentos de texto simples. Criar, abrir e converter documentos no TextEdit no Mac.

Este programa aceita o carimbo de data/hora fornecido, com precisão de segundos, analisa-o uma vez e cria três representações a partir do mesmo instant. A Apple documenta o ISO8601DateFormatter para analisar e gerar representações ISO 8601 e sua opção withInternetDateTime para o formato RFC 3339. ISO8601DateFormatter, withInternetDateTime.

import Foundation

// Synthetic publication data. Change these two values as needed.
let sourceTimestamp = "2025-07-15T00:30:00Z"
let destinationIdentifier = "America/Los_Angeles"

enum ConversionError: Error {
    case invalidTimestamp(String)
    case unknownTimeZone(String)
}

let inputFormatter = ISO8601DateFormatter()
inputFormatter.formatOptions = [.withInternetDateTime]
inputFormatter.timeZone = TimeZone(secondsFromGMT: 0)

guard let instant = inputFormatter.date(from: sourceTimestamp) else {
    throw ConversionError.invalidTimestamp(sourceTimestamp)
}

guard let destination = TimeZone(identifier: destinationIdentifier) else {
    throw ConversionError.unknownTimeZone(destinationIdentifier)
}

let destinationFormatter = ISO8601DateFormatter()
destinationFormatter.formatOptions = [.withInternetDateTime]
destinationFormatter.timeZone = destination

let publicationLabelStyle = Date.FormatStyle(
    date: .long,
    time: .complete,
    locale: Locale(identifier: "en_GB"),
    calendar: Calendar(identifier: .gregorian),
    timeZone: destination
)

let publicationDateStyle = Date.FormatStyle(
    date: .long,
    time: .omitted,
    locale: Locale(identifier: "en_GB"),
    calendar: Calendar(identifier: .gregorian),
    timeZone: destination
)

print("Source instant: \(inputFormatter.string(from: instant))")
print("Destination zone: \(destination.identifier)")
print("Destination timestamp: \(destinationFormatter.string(from: instant))")
print("Publication label: \(instant.formatted(publicationLabelStyle))")
print("Publication date: \(instant.formatted(publicationDateStyle))")

Execute o programa salvo:

swift "$HOME/Desktop/publication-time.swift"

Para os valores fornecidos, o carimbo de data/hora de destino deve ser 2025-07-14T17:30:00-07:00, e a data da publicação deve corresponder a 14 de julho de 2025. O rótulo legível também inclui a hora e as informações de fuso; a redação e a pontuação exatas são definidas pelo sistema de formatação.

O programa Swift foi verificado com base na documentação da API consultada, mas não foi executado no ambiente de pesquisa porque o Swift não estava disponível. As conversões numéricas do exemplo foram verificadas separadamente com as APIs de data, hora e fuso horário do Python.

Quais configurações controlam o resultado?

O inicializador do formatador aceita configurações separadas para localidade, calendário e fuso horário. Aqui, en_GB solicita as convenções de formatação do inglês britânico, o calendário gregoriano fornece o sistema de datas e destination determina a data e a hora locais. Altere o identificador do fuso quando precisar de outro destino; altere a localidade quando precisar de outra convenção de apresentação. init(date:time:locale:calendar:timeZone:capitalizationContext:).

O resultado que contém somente a data ainda vem diretamente de instant. Definir time: .omitted remove a hora do rótulo de saída. Isso não exige criar um novo instante à meia-noite.

Confira as passagens pela meia-noite e os deslocamentos sazonais

Use os exemplos sintéticos a seguir para conferir se o resultado preserva a operação pretendida. São carimbos de data/hora ilustrativos de publicações, com representações calculadas no destino.

Instante original Fuso de destino Representação no destino
2025-01-15T00:30:00Z America/Los_Angeles 2025-01-14T16:30:00-08:00
2025-07-15T00:30:00Z America/Los_Angeles 2025-07-14T17:30:00-07:00
2025-07-15T00:30:00Z Asia/Tokyo 2025-07-15T09:30:00+09:00
2025-07-15T23:30:00Z Asia/Tokyo 2025-07-16T08:30:00+09:00

As duas primeiras linhas mostram por que um ajuste fixo não é suficiente para um destino nomeado: o deslocamento aplicável pode depender do instante. As duas últimas linhas mostram por que você deve calcular a data completa do calendário no destino, junto com a hora. Uma publicação pode aparecer no dia anterior, no mesmo dia ou no dia seguinte.

Fusos nomeados usam regras de um banco de dados de fusos horários. A IANA informa que o macOS usa seu banco de dados e que as atualizações costumam chegar aos clientes por meio de atualizações do sistema operacional. Se os resultados forem diferentes entre computadores, confira os identificadores de fuso e as atualizações disponíveis antes de alterar o carimbo de data/hora de origem. Dados de fuso horário e horário de verão.

O que fazer quando a entrada ou a saída for inesperada?

Faça estas verificações na ordem indicada:

  1. Confirme que a origem identifica um instante. Preserve seu Z ou deslocamento numérico. Um valor que contém somente uma data ou uma leitura do relógio local exige informações adicionais.
  2. Confirme o identificador de destino. Use um identificador como America/Los_Angeles. O inicializador da Apple retorna nil para um identificador desconhecido; este programa é interrompido com um erro em vez de substituir o fuso por outro.
  3. Confira o formato de carimbo de data/hora aceito. O exemplo está configurado para carimbos de data/hora de Internet com precisão de segundos. Frações de segundo ou outra representação de entrada exigem uma configuração de análise adequada. Preserve a entrada original ao fazer essa alteração.
  4. Compare o carimbo de data/hora numérico de destino. Use a data, a hora e o deslocamento para avaliar a conversão antes de investigar a pontuação de exibição.
  5. Confira se todas as saídas usam o instant original. Remova qualquer etapa intermediária que formate um rótulo e depois o analise para a conversão seguinte. init(identifier:), ISO8601DateFormatter.

Um fuso nomeado e um deslocamento também podem ser fornecidos juntos em um carimbo de data/hora estendido conforme a RFC 9557. A existência desse padrão não comprova que as anotações de fuso entre colchetes sejam aceitas pelo analisador deste exemplo. Mantenha o identificador de destino no valor separado destinationIdentifier usado acima, a menos que você implemente e verifique deliberadamente um caminho de entrada para o formato estendido. RFC 9557.

Para um rótulo de publicação, preserve o instante original como valor reutilizável e gere o texto de cada destino a partir dele. Assim, você pode alterar o fuso de destino, o idioma de exibição ou os detalhes visíveis, mantendo todos os rótulos vinculados ao mesmo momento de publicação.

Fontes