Back

Exibindo Horários Legíveis no Navegador

Exibindo Horários Legíveis no Navegador

Seu servidor armazena timestamps em UTC. Seus usuários vivem em dezenas de fusos horários. A lacuna entre essas duas realidades—strings ISO brutas versus “há 2 horas”—determina se sua interface parece nativa ou estranha.

Os navegadores modernos agora lidam com horários legíveis em JavaScript sem bibliotecas de terceiros. Este artigo cobre as APIs nativas que você deve usar: Intl.DateTimeFormat, Intl.RelativeTimeFormat, Intl.DurationFormat e a API Temporal para lógica com reconhecimento de fuso horário.

Principais Conclusões

  • Use Intl.DateTimeFormat para timestamps absolutos com reconhecimento de localidade, passando identificadores de fuso horário IANA diretamente para evitar cálculos manuais de deslocamento.
  • Use Intl.RelativeTimeFormat com uma pequena função auxiliar para produzir frases naturais como “ontem” ou “há 3 horas”.
  • Use Intl.DurationFormat para tempo decorrido e contagens regressivas, mas verifique o suporte do navegador, pois a disponibilidade baseline chegou apenas em 2025.
  • A API Temporal substitui o objeto Date propenso a erros por tipos explícitos e imutáveis—adote-a para novos projetos enquanto confia nos formatadores Intl para bases de código existentes.

Timestamps Absolutos com Intl.DateTimeFormat

Quando os usuários precisam de datas e horários exatos, Intl.DateTimeFormat lida com a localização automaticamente. Ela respeita a localidade do usuário e formata datas de acordo com convenções regionais.

const date = new Date('2026-03-15T14:30:00Z')

const formatter = new Intl.DateTimeFormat('en-US', {
  dateStyle: 'medium',
  timeStyle: 'short',
  timeZone: 'America/New_York'
})

console.log(formatter.format(date)) // "Mar 15, 2026, 10:30 AM"

A API aceita identificadores de fuso horário IANA diretamente, eliminando cálculos manuais de deslocamento. Para formatação local do usuário, detecte o fuso horário automaticamente:

const userTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone

Isso retorna valores como "Europe/London" ou "Asia/Tokyo", que você pode passar diretamente para os formatadores.

Tempo Relativo com Intl.RelativeTimeFormat

Feeds sociais, notificações e registros de atividades se beneficiam de timestamps relativos. Intl.RelativeTimeFormat produz frases como “há 3 dias” ou “em 2 horas” com localização adequada.

const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' })

rtf.format(-1, 'day')    // "yesterday"
rtf.format(-3, 'hour')   // "3 hours ago"
rtf.format(2, 'week')    // "in 2 weeks"

A opção numeric: 'auto' produz linguagem natural (“yesterday”) em vez de números literais (“1 day ago”) quando apropriado.

Você precisa calcular a diferença por conta própria—a API formata valores, não datas. Uma função auxiliar simples funciona:

function getRelativeTime(date) {
  const now = Date.now()
  const diffInSeconds = Math.round((date - now) / 1000)
  const units = [
    { unit: 'year', seconds: 31536000 },
    { unit: 'month', seconds: 2592000 },
    { unit: 'day', seconds: 86400 },
    { unit: 'hour', seconds: 3600 },
    { unit: 'minute', seconds: 60 },
    { unit: 'second', seconds: 1 }
  ]

  for (const { unit, seconds } of units) {
    if (Math.abs(diffInSeconds) >= seconds) {
      const value = Math.round(diffInSeconds / seconds)
      return new Intl.RelativeTimeFormat('en', { numeric: 'auto' })
        .format(value, unit)
    }
  }
  return 'just now'
}

Os valores de mês e ano acima usam aproximações fixas de segundos. Para diferenças precisas de calendário considerando comprimentos variáveis de meses ou anos bissextos, use Temporal ou uma biblioteca de datas dedicada em vez de constantes fixas de segundos.

Observe que Math.round pode ocasionalmente empurrar um valor para a próxima unidade (por exemplo, 89 segundos arredonda para 1 quando dividido por 60, produzindo “1 minute ago” em vez de “89 seconds ago”). Se você precisar de limites mais rigorosos, use Math.trunc em vez disso.

Formatação de Duração com Intl.DurationFormat

Para tempo decorrido, contagens regressivas ou durações de vídeo, Intl.DurationFormat fornece saída consistente em todas as localidades:

const duration = { hours: 2, minutes: 45, seconds: 30 }

const df = new Intl.DurationFormat('en', { style: 'long' })
console.log(df.format(duration)) // "2 hours, 45 minutes, 30 seconds"

const dfShort = new Intl.DurationFormat('en', { style: 'digital' })
console.log(dfShort.format(duration)) // "2:45:30"

Esta API alcançou suporte baseline entre motores em 2025 e está disponível em navegadores modernos, embora você ainda deva confirmar a compatibilidade com sua matriz de suporte específica.

A API Temporal para Manipulação Mais Segura de Datas

A API Temporal aborda problemas antigos com o objeto Date do JavaScript—mutabilidade, confusão de fuso horário e inconsistências de análise. Temporal é suportado em versões modernas do Chromium e Firefox a partir de 2026, mas a detecção de recursos permanece essencial porque o suporte ainda não é universal em todos os navegadores.

if (typeof Temporal !== 'undefined') {
  const now = Temporal.Now.zonedDateTimeISO('America/Los_Angeles')
  console.log(now.toString())
}

Temporal fornece tipos distintos para diferentes conceitos: Temporal.PlainDate para datas de calendário, Temporal.PlainTime para horário de relógio de parede e Temporal.ZonedDateTime para momentos com reconhecimento de fuso horário. Essa explicitação previne os bugs que assolam código baseado em Date.

Para novos projetos, Temporal oferece a base mais limpa. Para bases de código existentes, os formatadores Intl funcionam perfeitamente com objetos Date legados.

Recomendações Práticas

Armazene timestamps como strings UTC ISO 8601. Formate-os no lado do cliente usando as APIs Intl. Evite analisar strings de data não-ISO—elas se comportam de forma inconsistente entre navegadores.

Reutilize instâncias de formatadores ao formatar múltiplos timestamps. Criar um formatador uma vez e chamar format() repetidamente é significativamente mais rápido do que recriá-lo a cada chamada.

Use HTML semântico para acessibilidade:

<time datetime="2026-03-15T14:30:00Z">March 15, 2026</time>

Conclusão

A plataforma nativa agora lida com o que antes exigia Moment.js ou bibliotecas similares. Intl.DateTimeFormat cobre timestamps absolutos, Intl.RelativeTimeFormat cobre frases relativas, Intl.DurationFormat cobre tempo decorrido, e a API Temporal fornece uma base sólida para lógica de data com reconhecimento de fuso horário. Para horários legíveis no navegador, essas ferramentas integradas são tudo o que você precisa.

Perguntas Frequentes

Não. A API apenas formata um valor numérico e uma unidade em uma string localizada. Você deve calcular a diferença entre duas datas por conta própria e escolher a unidade apropriada antes de passá-las para o método format. A função auxiliar mostrada neste artigo é um padrão comum para esse cálculo.

Temporal está disponível em versões modernas do Chromium e Firefox a partir de 2026, mas ainda não é universalmente suportado em todos os navegadores. Sempre use detecção de recursos antes de chamar métodos Temporal e considere um polyfill se você precisar de ampla compatibilidade. Para formatação apenas, as APIs Intl já têm amplo suporte e funcionam bem com o objeto Date legado.

Construir um formatador Intl envolve resolver dados de localidade, regras de fuso horário e opções de formatação, o que tem um custo mensurável. Criar uma instância e chamar seu método format repetidamente é significativamente mais rápido do que reconstruir o formatador a cada invocação, especialmente ao renderizar longas listas de timestamps.

Por padrão, sim. Se você omitir a opção timeZone, o formatador usa o fuso horário do ambiente de execução, que em um navegador corresponde à configuração do sistema do usuário. Você pode recuperar esse valor explicitamente via Intl.DateTimeFormat().resolvedOptions().timeZone e passá-lo para outros formatadores ou enviá-lo para seu servidor.

Complete picture for complete understanding

Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.

Check our GitHub repo and join the thousands of developers in our community.

OpenReplay