ES2026 e Temporal API: Finalmente JavaScript Terá Manipulação de Datas Nativa e Decente
Olá HaWkers, depois de anos dependendo de bibliotecas externas como moment.js e date-fns, finalmente o JavaScript terá uma API de datas nativa que faz sentido. A Temporal API chegou ao Stage 4 e será oficialmente parte do ES2026, marcando uma das maiores evoluções da linguagem nos últimos anos.
Por que a comunidade JavaScript esperou tanto por isso? E o que muda na prática para os desenvolvedores?
O Problema Histórico do Date
O objeto Date do JavaScript é famoso por suas inconsistências.
Problemas Clássicos
Por que Date é problemático:
// Problema 1: Meses começam em 0
const date = new Date(2026, 0, 15); // Janeiro = 0, não 1
console.log(date); // 15 de Janeiro de 2026
// Problema 2: Mutabilidade perigosa
const original = new Date(2026, 5, 15);
const modified = original;
modified.setMonth(7); // Modifica AMBAS as variáveis!
console.log(original); // Agosto, não Junho!
// Problema 3: Parsing inconsistente
new Date('2026-01-15'); // Interpretado como UTC
new Date('01/15/2026'); // Interpretado como local
// Resultados diferentes dependendo do timezone!
// Problema 4: Sem suporte a timezones
const date2 = new Date();
// Como converter para timezone de Tokyo?
// Precisa de biblioteca externa ou cálculos manuais
Temporal API: A Solução
Imutável, precisa e intuitiva.
Tipos Principais
Objetos disponíveis no Temporal:
// Temporal.PlainDate - Apenas data, sem hora ou timezone
const date = Temporal.PlainDate.from('2026-01-15');
console.log(date.year); // 2026
console.log(date.month); // 1 (Janeiro = 1, finalmente!)
console.log(date.day); // 15
// Temporal.PlainTime - Apenas hora, sem data
const time = Temporal.PlainTime.from('14:30:00');
console.log(time.hour); // 14
console.log(time.minute); // 30
// Temporal.PlainDateTime - Data e hora, sem timezone
const dateTime = Temporal.PlainDateTime.from('2026-01-15T14:30:00');
// Temporal.ZonedDateTime - Data, hora E timezone
const zonedDT = Temporal.ZonedDateTime.from({
timeZone: 'America/Sao_Paulo',
year: 2026,
month: 1,
day: 15,
hour: 14,
minute: 30
});
// Temporal.Instant - Ponto exato no tempo (timestamp)
const instant = Temporal.Instant.from('2026-01-15T17:30:00Z');
// Temporal.Duration - Duração de tempo
const duration = Temporal.Duration.from({ hours: 2, minutes: 30 });Operações Imutáveis
Nunca mais modificar acidentalmente:
const date = Temporal.PlainDate.from('2026-01-15');
// Adicionar dias retorna NOVA instância
const nextWeek = date.add({ days: 7 });
console.log(date.toString()); // 2026-01-15 (original intacto)
console.log(nextWeek.toString()); // 2026-01-22 (nova instância)
// Subtrair tempo
const lastMonth = date.subtract({ months: 1 });
console.log(lastMonth.toString()); // 2025-12-15
// Modificar campos específicos
const newYear = date.with({ year: 2027 });
console.log(newYear.toString()); // 2027-01-15
// Comparações diretas
const date1 = Temporal.PlainDate.from('2026-01-15');
const date2 = Temporal.PlainDate.from('2026-02-20');
console.log(Temporal.PlainDate.compare(date1, date2)); // -1 (date1 < date2)
console.log(date1.equals(date2)); // false
Timezones Finalmente Resolvidos
Conversões sem dor de cabeça.
Trabalhando com Fusos Horários
// Criar data com timezone específico
const spDateTime = Temporal.ZonedDateTime.from({
timeZone: 'America/Sao_Paulo',
year: 2026,
month: 1,
day: 15,
hour: 10,
minute: 0
});
console.log(spDateTime.toString());
// 2026-01-15T10:00:00-03:00[America/Sao_Paulo]
// Converter para outro timezone
const tokyoDateTime = spDateTime.withTimeZone('Asia/Tokyo');
console.log(tokyoDateTime.toString());
// 2026-01-15T22:00:00+09:00[Asia/Tokyo]
// Mesmo instante, diferentes representações locais
console.log(spDateTime.toInstant().equals(tokyoDateTime.toInstant())); // true
// Obter offset atual
console.log(spDateTime.offset); // -03:00
// Listar todos os timezones disponíveis
const timezones = Temporal.TimeZone.getAvailableTimeZones();
console.log(timezones.includes('America/Sao_Paulo')); // trueHorário de Verão
Tratamento automático de DST:
// Temporal lida automaticamente com horário de verão
const beforeDST = Temporal.ZonedDateTime.from({
timeZone: 'America/New_York',
year: 2026,
month: 3,
day: 8,
hour: 1,
minute: 30
});
// Adicionar 2 horas atravessando mudança de DST
const afterDST = beforeDST.add({ hours: 2 });
console.log(afterDST.hour); // 4 (não 3, porque pulou uma hora)
// Verificar se está em horário de verão
console.log(beforeDST.inDST); // false
console.log(afterDST.inDST); // true
Duration: Cálculos de Período
Intervalos e durações precisas.
Operações com Duração
// Criar duração
const duration = Temporal.Duration.from({
years: 1,
months: 2,
days: 15,
hours: 8,
minutes: 30
});
console.log(duration.total('days')); // Total aproximado em dias
// Diferença entre datas
const start = Temporal.PlainDate.from('2026-01-15');
const end = Temporal.PlainDate.from('2026-06-20');
const diff = start.until(end);
console.log(diff.months); // 5
console.log(diff.days); // 5
// Especificar unidades desejadas
const diffInDays = start.until(end, { largestUnit: 'day' });
console.log(diffInDays.days); // 156
// Arredondar duração
const preciseDuration = Temporal.Duration.from({
hours: 2,
minutes: 45,
seconds: 30
});
const rounded = preciseDuration.round({
smallestUnit: 'minute',
roundingMode: 'halfExpand'
});
console.log(rounded.minutes); // 46Aplicação Prática: Countdown
function getCountdown(targetDate) {
const now = Temporal.Now.plainDateTimeISO();
const target = Temporal.PlainDateTime.from(targetDate);
if (Temporal.PlainDateTime.compare(now, target) >= 0) {
return { expired: true };
}
const duration = now.until(target, {
largestUnit: 'day'
});
return {
expired: false,
days: duration.days,
hours: duration.hours,
minutes: duration.minutes,
seconds: duration.seconds
};
}
const countdown = getCountdown('2026-12-31T23:59:59');
console.log(`${countdown.days}d ${countdown.hours}h ${countdown.minutes}m`);
Comparação: Temporal vs Bibliotecas
Adeus dependências desnecessárias.
Antes (com date-fns)
import {
format,
addDays,
differenceInDays,
parseISO,
isAfter
} from 'date-fns';
import { zonedTimeToUtc, utcToZonedTime } from 'date-fns-tz';
const date = parseISO('2026-01-15');
const nextWeek = addDays(date, 7);
const formatted = format(nextWeek, 'dd/MM/yyyy');
// Timezone requer pacote adicional
const spTime = utcToZonedTime(new Date(), 'America/Sao_Paulo');Depois (com Temporal)
// Nativo, sem imports
const date = Temporal.PlainDate.from('2026-01-15');
const nextWeek = date.add({ days: 7 });
const formatted = nextWeek.toLocaleString('pt-BR');
// Timezone nativo
const spTime = Temporal.Now.zonedDateTimeISO('America/Sao_Paulo');Comparativo de Bundle Size
Impacto no tamanho do projeto:
| Biblioteca | Tamanho (minified) | Com Temporal |
|---|---|---|
| moment.js | 72 KB | 0 KB |
| date-fns (full) | 85 KB | 0 KB |
| dayjs | 7 KB | 0 KB |
| luxon | 68 KB | 0 KB |
| Temporal | Nativo | 0 KB |
💡 Nota: Temporal é nativo do browser/runtime, então não adiciona nada ao bundle size da sua aplicação.
Casos de Uso Práticos
Exemplos do mundo real.
Agendamento de Reuniões
function scheduleGlobalMeeting(participants) {
// Cada participante com seu timezone
const schedules = participants.map(p => ({
name: p.name,
timezone: p.timezone,
workStart: Temporal.PlainTime.from('09:00'),
workEnd: Temporal.PlainTime.from('18:00')
}));
// Encontrar horário que funciona para todos
const referenceDate = Temporal.Now.plainDateISO();
for (let hour = 0; hour < 24; hour++) {
const testTime = Temporal.PlainDateTime.from({
year: referenceDate.year,
month: referenceDate.month,
day: referenceDate.day,
hour: hour,
minute: 0
});
const worksForAll = schedules.every(s => {
const localTime = testTime
.toZonedDateTime('UTC')
.withTimeZone(s.timezone)
.toPlainTime();
return Temporal.PlainTime.compare(localTime, s.workStart) >= 0 &&
Temporal.PlainTime.compare(localTime, s.workEnd) <= 0;
});
if (worksForAll) {
return { hour, suitable: true };
}
}
return { suitable: false };
}
Adoção e Compatibilidade
Quando e como usar.
Status Atual
Disponibilidade em 2026:
Browsers:
- Chrome 144+: Suporte completo
- Firefox: Em desenvolvimento
- Safari: Em desenvolvimento
Runtimes:
- Node.js 24+: Suporte completo
- Deno: Suporte completo
- Bun: Suporte completo
Polyfill disponível:
npm install @js-temporal/polyfill// Usar polyfill enquanto browsers atualizam
import { Temporal } from '@js-temporal/polyfill';
const now = Temporal.Now.plainDateTimeISO();Migração Gradual
Estratégia de transição:
// Wrapper para migração gradual
function toTemporal(date) {
if (date instanceof Date) {
return Temporal.Instant
.fromEpochMilliseconds(date.getTime())
.toZonedDateTimeISO('UTC');
}
return date;
}
function toDate(temporal) {
if (temporal instanceof Temporal.ZonedDateTime) {
return new Date(temporal.epochMilliseconds);
}
return temporal;
}
// Uso durante migração
const legacyDate = new Date();
const temporal = toTemporal(legacyDate);
// ... operações com Temporal
const backToDate = toDate(temporal);ES2026 com Temporal API representa uma das maiores evoluções do JavaScript. Finalmente teremos manipulação de datas que faz sentido, é imutável por padrão e suporta timezones nativamente. Se você ainda está usando moment.js ou date-fns para operações básicas, prepare-se para simplificar muito seu código em breve.
Se você quer se aprofundar nas novidades do JavaScript moderno, recomendo ver outro artigo: Signals: O Novo Padrão de Reatividade do JavaScript onde você descobrirá como a reatividade está evoluindo na linguagem.
Bora pra cima! 🦅
📚 Quer Aprofundar Seus Conhecimentos em JavaScript?
Este artigo cobriu a Temporal API, mas há muito mais para explorar no mundo do desenvolvimento moderno.
Desenvolvedores que investem em conhecimento sólido e estruturado tendem a ter mais oportunidades no mercado.
Material de Estudo Completo
Se você quer dominar JavaScript do básico ao avançado, preparei um guia completo:
Opções de investimento:
- 1x de R$27,00 no cartão
- ou R$27,00 à vista no Pix
💡 Material atualizado com as melhores práticas do mercado

