Introdução: por que tempo é uma dor
\n\nTodo 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\nTrabalhar 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\nNeste 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\nPor que o JavaScript lida com datas de forma tão estranha?
\n\nVamos 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
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
E é aí que começa a confusão. Suponha que você escreva:
\n\nconst now = new Date();\nconsole.log(now.getHours()); // 14 — se você está no MSK\nconsole.log(now.getUTCHours()); // 11 — UTC\n\nSe 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.
Intl.DateTimeFormat: o salvador nativo
\n\nMuitos 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.
Exemplo básico
\n\nconst 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\nObserve: 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.
Lista de todos os fusos horários
\n\nSe você não sabe qual fuso horário especificar, pode obter a lista completa:
\n\nconsole.log(Intl.supportedValuesOf('timeZone'));\n// ["Africa/Abidjan", "Africa/Accra", ..., "Pacific/Wallis"]\n\nEsta lista inclui mais de 500 fusos horários. Use-a para garantir que seu fuso horário seja suportado.
\n\nMoment.js: clássico, mas com ressalvas
\n\nPor 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.
Instalação
\n\nnpm install moment moment-timezone\n\nExemplo com fusos horários
\n\nconst 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\nImportante: moment.js é uma biblioteca legada. Os próprios autores recomendam a transição