Fusos horários em JavaScript: como não enlouquecer

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução: por que tempo é uma dor

\n\n

Todo mundo que já escreveu código em JavaScript já enfrentou essa dor. Você mostra ao usuário a hora 12:00, e ele escreve: "Aqui são 14:00, tudo quebrou". Ou você salva a data no banco de dados e, ao carregar, ela se desloca uma hora para trás. Familiar?

\n\n

Trabalhar com fusos horários em JavaScript é aquele tópico que muitos desenvolvedores deixam "para depois". E é uma pena. Porque se você não resolver isso imediatamente, depois terá que reescrever metade da aplicação.

\n\n

Neste artigo, vou mostrar como trabalhar corretamente com fusos horários em JS, apresentar exemplos reais de código e dar algumas dicas que economizarão horas de depuração. Vamos lá!

\n\n

Por que o JavaScript lida com datas de forma tão estranha?

\n\n

Vamos começar pelo principal: o objeto Date em JavaScript não é, para dizer o mínimo, um presente. Ele armazena o tempo em milissegundos desde 1º de janeiro de 1970 UTC. E tudo bem, mas:

\n\n
    \n
  • getMonth() retorna meses de 0 a 11 (janeiro é 0, dezembro é 11)
  • \n
  • Os métodos getHours(), getMinutes() retornam a hora no fuso horário local do usuário
  • \n
  • E os métodos getUTCHours(), getUTCMinutes() retornam em UTC
  • \n
\n\n

E é aí que começa a confusão. Suponha que você escreva:

\n\n
const now = new Date();\nconsole.log(now.getHours());      // 14 — se você está no MSK\nconsole.log(now.getUTCHours());   // 11 — UTC
\n\n

Se você salvar now no banco de dados e depois recuperá-lo no servidor em outro fuso horário, terá uma bagunça. Portanto, a primeira regra para trabalhar com datas e fusos horários em JavaScript é: sempre armazene o tempo em UTC e converta no cliente.

\n\n

Intl.DateTimeFormat: o salvador nativo

\n\n

Muitos não sabem, mas o JavaScript moderno possui uma API nativa poderosa para trabalhar com formatação de datas considerando o fuso horário. É o Intl.DateTimeFormat. Ele suporta todos os principais fusos horários e consegue formatar datas de forma elegante.

\n\n

Exemplo básico

\n\n
const date = new Date('2025-03-15T12:00:00Z');\n\nconst formatter = new Intl.DateTimeFormat('pt-BR', {\n    timeZone: 'America/New_York',\n    year: 'numeric',\n    month: 'long',\n    day: 'numeric',\n    hour: '2-digit',\n    minute: '2-digit'\n});\n\nconsole.log(formatter.format(date)); \n// "15 de março de 2025, 08:00" — hora em Nova York
\n\n

Observe: passamos a data em UTC (letra Z no final), e o Intl.DateTimeFormat a converte para o fuso horário desejado. Isso é ideal para exibir a hora para usuários de diferentes regiões.

\n\n

Lista de todos os fusos horários

\n\n

Se você não sabe qual fuso horário especificar, pode obter a lista completa:

\n\n
console.log(Intl.supportedValuesOf('timeZone'));\n// ["Africa/Abidjan", "Africa/Accra", ..., "Pacific/Wallis"]
\n\n

Esta lista inclui mais de 500 fusos horários. Use-a para garantir que seu fuso horário seja suportado.

\n\n

Moment.js: clássico, mas com ressalvas

\n\n

Por muito tempo, o moment.js foi o padrão para trabalhar com datas em JavaScript. Ele consegue analisar, formatar, manipular datas e, claro, trabalhar com fusos horários através do plugin moment-timezone.

\n\n

Instalação

\n\n
npm install moment moment-timezone
\n\n

Exemplo com fusos horários

\n\n
const moment = require('moment-timezone');\n\nconst now = moment();\nconsole.log(now.tz('Europe/Moscow').format('YYYY-MM-DD HH:mm'));\n// 2025-03-15 14:00 — horário de Moscou\n\nconst nyTime = moment.tz('2025-03-15 12:00', 'America/New_York');\nconsole.log(nyTime.clone().tz('Europe/Moscow').format('YYYY-MM-DD HH:mm'));\n// 2025-03-15 19:00 — diferença de 7 horas
\n\n

Importante: moment.js é uma biblioteca legada. Os próprios autores recomendam a transição

Blogs

Book Recommendations