Português

Um guia detalhado sobre a API Temporal do JavaScript, uma solução moderna para lidar com datas e horas de forma eficaz em diversos contextos internacionais.

API Temporal do JavaScript: Manipulação Moderna de Data e Hora para um Público Global

O objeto `Date` do JavaScript tem sido, há muito tempo, uma fonte de frustração para desenvolvedores. Sua mutabilidade, API inconsistente e suporte fraco a fusos horários levaram à criação de inúmeras bibliotecas, como Moment.js e date-fns, para preencher as lacunas. Agora, com a API Temporal, o JavaScript oferece uma solução moderna e integrada para lidar com datas e horas com maior clareza e precisão. Este artigo fornece uma visão abrangente da API Temporal, focando em suas funcionalidades, benefícios e uso em diversos contextos internacionais.

O que é a API Temporal?

A API Temporal é um novo objeto global no JavaScript, projetado para resolver as deficiências do objeto `Date`. Ela fornece uma API limpa e imutável para trabalhar com datas, horas, fusos horários e sistemas de calendário. Crucialmente, ela visa representar conceitos de data e hora de uma forma que se alinha mais de perto com o uso e as expectativas do mundo real, tornando a internacionalização muito mais simples.

Principais Características:

Objetos Temporais Básicos

A API Temporal introduz vários novos tipos de objetos. Aqui estão alguns dos principais:

Trabalhando com Datas

Criando um `Temporal.PlainDate`

Para criar um `Temporal.PlainDate`, você pode usar o construtor:

const plainDate = new Temporal.PlainDate(2024, 10, 27); // Ano, Mês (1-12), Dia
console.log(plainDate.toString()); // Saída: 2024-10-27

Você também pode usar o método `from`, que aceita uma string no formato ISO 8601:

const plainDateFromString = Temporal.PlainDate.from('2024-10-27');
console.log(plainDateFromString.toString()); // Saída: 2024-10-27

Obtendo Componentes da Data

Você pode acessar componentes individuais da data usando propriedades como `year`, `month` e `day`:

console.log(plainDate.year); // Saída: 2024
console.log(plainDate.month); // Saída: 10
console.log(plainDate.day); // Saída: 27

Aritmética de Datas

Para adicionar ou subtrair dias, semanas, meses ou anos, use os métodos `plus` e `minus`. Esses métodos retornam um novo objeto `Temporal.PlainDate`:

const nextWeek = plainDate.plus({ days: 7 });
console.log(nextWeek.toString()); // Saída: 2024-11-03

const lastMonth = plainDate.minus({ months: 1 });
console.log(lastMonth.toString()); // Saída: 2024-09-27

Comparando Datas

Você pode comparar datas usando o método `compare`:

const date1 = new Temporal.PlainDate(2024, 10, 27);
const date2 = new Temporal.PlainDate(2024, 11, 15);

console.log(Temporal.PlainDate.compare(date1, date2)); // Saída: -1 (date1 é anterior a date2)

Trabalhando com Horas

Criando um `Temporal.PlainTime`

Para criar um `Temporal.PlainTime`, use o construtor:

const plainTime = new Temporal.PlainTime(10, 30, 0); // Hora, Minuto, Segundo
console.log(plainTime.toString()); // Saída: 10:30:00

Ou use o método `from` com uma string de hora ISO 8601:

const plainTimeFromString = Temporal.PlainTime.from('10:30:00');
console.log(plainTimeFromString.toString()); // Saída: 10:30:00

Obtendo Componentes da Hora

console.log(plainTime.hour); // Saída: 10
console.log(plainTime.minute); // Saída: 30
console.log(plainTime.second); // Saída: 0

Aritmética de Horas

const later = plainTime.plus({ minutes: 15 });
console.log(later.toString()); // Saída: 10:45:00

Trabalhando com Data e Hora Juntos

Criando um `Temporal.PlainDateTime`

Você pode criar um `Temporal.PlainDateTime` diretamente ou combinando um `Temporal.PlainDate` e um `Temporal.PlainTime`:

const plainDateTime = new Temporal.PlainDateTime(2024, 10, 27, 10, 30, 0);
console.log(plainDateTime.toString()); // Saída: 2024-10-27T10:30:00

const date = new Temporal.PlainDate(2024, 10, 27);
const time = new Temporal.PlainTime(10, 30, 0);
const combinedDateTime = date.toPlainDateTime(time);
console.log(combinedDateTime.toString()); // Saída: 2024-10-27T10:30:00

Fusos Horários

Lidar com fusos horários corretamente é crucial para aplicações que lidam com usuários em diferentes locais. A API Temporal fornece um suporte robusto a fusos horários através dos objetos `Temporal.ZonedDateTime` e `Temporal.TimeZone`.

Criando um `Temporal.ZonedDateTime`

Para criar um `Temporal.ZonedDateTime`, você precisa de um `Temporal.PlainDateTime` e um identificador de fuso horário. Os identificadores de fuso horário são baseados no banco de dados de fusos horários da IANA (ex: `America/Los_Angeles`, `Europe/London`, `Asia/Tokyo`).

const plainDateTime = new Temporal.PlainDateTime(2024, 10, 27, 10, 30, 0);
const timeZone = 'America/Los_Angeles';
const zonedDateTime = plainDateTime.toZonedDateTime(timeZone);
console.log(zonedDateTime.toString()); // Saída: 2024-10-27T10:30:00-07:00[America/Los_Angeles] (O deslocamento dependerá das regras do horário de verão)

Alternativamente, crie um `Temporal.ZonedDateTime` a partir de um `Instant`.

const instant = Temporal.Instant.fromEpochSeconds(1666866600); // Exemplo de timestamp
const zonedDateTimeFromInstant = instant.toZonedDateTimeISO(timeZone); // Fuso horário como 'America/Los_Angeles'
console.log(zonedDateTimeFromInstant.toString());

Convertendo Entre Fusos Horários

Você pode converter um `Temporal.ZonedDateTime` para um fuso horário diferente usando o método `withTimeZone`:

const newTimeZone = 'Europe/London';
const zonedDateTimeInLondon = zonedDateTime.withTimeZone(newTimeZone);
console.log(zonedDateTimeInLondon.toString()); // Saída: 2024-10-27T18:30:00+01:00[Europe/London]

Trabalhando com Deslocamentos de Fuso Horário

O método `getOffsetStringFor` do objeto `Temporal.TimeZone` fornece a string de deslocamento para um determinado `Temporal.Instant`:

const timeZoneObject = new Temporal.TimeZone(timeZone);
const offsetString = timeZoneObject.getOffsetStringFor(zonedDateTime.toInstant());
console.log(offsetString); // Saída: -07:00 (Dependendo das regras do horário de verão)

É essencial usar os identificadores de fuso horário da IANA corretos para cálculos precisos. Esses identificadores são mantidos e atualizados regularmente para refletir mudanças no horário de verão e nas fronteiras dos fusos horários.

Durações

O objeto `Temporal.Duration` representa um período de tempo. Ele pode ser usado para adicionar ou subtrair de datas e horas.

Criando uma `Temporal.Duration`

Você pode criar uma `Temporal.Duration` usando o construtor, especificando os anos, meses, dias, horas, minutos, segundos, milissegundos, microssegundos e nanossegundos:

const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 9); // Anos, Meses, Dias, Horas, Minutos, Segundos, Milissegundos, Microssegundos, Nanossegundos
console.log(duration.toString()); // Saída: P1Y2M3DT4H5M6.007008009S

Ou usando uma string de duração ISO 8601:

const durationFromString = Temporal.Duration.from('P1Y2M3DT4H5M6S');
console.log(durationFromString.toString()); // Saída: P1Y2M3DT4H5M6S

Adicionando Durações a Datas e Horas

const plainDate = new Temporal.PlainDate(2024, 10, 27);
const duration = new Temporal.Duration(0, 0, 7); // 7 dias
const newDate = plainDate.plus(duration);
console.log(newDate.toString()); // Saída: 2024-11-03

Note que adicionar durações que envolvem meses ou anos a datas requer consideração cuidadosa, pois o número de dias em um mês ou ano pode variar.

Sistemas de Calendário

A API Temporal suporta diferentes sistemas de calendário além do calendário gregoriano. Isso é crucial para aplicações que precisam lidar com datas em vários contextos culturais. Embora o suporte ainda esteja evoluindo, ele fornece uma base para expansão futura.

Usando Calendários Alternativos

Para usar um calendário específico, você pode especificá-lo ao criar objetos Temporal:

const hebrewDate = new Temporal.PlainDate(5785, 1, 1, { calendar: 'hebrew' });
console.log(hebrewDate.toString()); // A saída específica pode variar dependendo da implementação e formatação. Requer polyfill em muitos ambientes no momento da escrita.

Importante: O suporte para calendários não gregorianos pode exigir polyfills ou suporte específico do navegador/ambiente. Verifique a documentação da API Temporal e as tabelas de compatibilidade de navegadores para obter as informações mais recentes.

Formatando Datas e Horas

Embora a API Temporal se concentre na manipulação de data e hora, a formatação é normalmente tratada pelo objeto `Intl.DateTimeFormat`, que faz parte da API de Internacionalização. Os objetos Temporal funcionam perfeitamente com `Intl.DateTimeFormat`.

Usando `Intl.DateTimeFormat`

Veja como formatar um `Temporal.PlainDate` usando `Intl.DateTimeFormat`:

const plainDate = new Temporal.PlainDate(2024, 10, 27);
const formatter = new Intl.DateTimeFormat('en-US', { year: 'numeric', month: 'long', day: 'numeric' });
console.log(formatter.format(plainDate)); // Saída: October 27, 2024

const formatterGerman = new Intl.DateTimeFormat('de-DE', { year: 'numeric', month: 'long', day: 'numeric' });
console.log(formatterGerman.format(plainDate)); // Saída: 27. Oktober 2024

Você pode personalizar as opções de formato para atender às suas necessidades. O primeiro argumento para `Intl.DateTimeFormat` é a localidade, que determina o idioma e as convenções regionais usadas para a formatação. Usar diferentes localidades (ex: 'en-US', 'de-DE', 'fr-FR', 'ja-JP') produz diferentes formatos de saída.

Formatando `Temporal.ZonedDateTime`

A formatação de `Temporal.ZonedDateTime` é semelhante, mas você também pode incluir informações de fuso horário na saída:

const plainDateTime = new Temporal.PlainDateTime(2024, 10, 27, 10, 30, 0);
const timeZone = 'America/Los_Angeles';
const zonedDateTime = plainDateTime.toZonedDateTime(timeZone);

const formatter = new Intl.DateTimeFormat('en-US', { year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric', timeZoneName: 'short' });
console.log(formatter.format(zonedDateTime)); // Saída: October 27, 2024, 10:30 AM PDT (A abreviação do fuso horário depende das regras do horário de verão)

Melhores Práticas de Internacionalização

Ao trabalhar com datas e horas em um contexto global, tenha em mente as seguintes melhores práticas:

Comparando a API Temporal com o Objeto Date Legado

Aqui está uma tabela destacando as principais diferenças e vantagens da API Temporal em comparação com o objeto `Date` legado:

Característica Objeto `Date` Legado API Temporal
Mutabilidade Mutável (modifica o objeto original) Imutável (retorna novos objetos)
Suporte a Fuso Horário Limitado e frequentemente problemático Robusto e preciso, baseado no banco de dados de fusos horários da IANA
API Inconsistente e difícil de usar Clara, consistente e intuitiva
Precisão Milissegundo Nanossegundo
Sistemas de Calendário Limitado ao Gregoriano Suporta sistemas de calendário alternativos (com suporte em evolução)
Internacionalização Requer bibliotecas externas para internacionalização robusta Suporte integrado e integração perfeita com `Intl.DateTimeFormat`

Suporte de Navegadores e Polyfills

Como uma API relativamente nova, o suporte dos navegadores para a API Temporal ainda está evoluindo. Verifique as tabelas de compatibilidade de navegadores mais recentes (por exemplo, na MDN Web Docs) para ver quais navegadores e ambientes a suportam nativamente. Para navegadores mais antigos ou ambientes sem suporte nativo, você pode usar polyfills para fornecer a funcionalidade da API Temporal. Pesquise por "Temporal API polyfill" na web para encontrar opções adequadas.

Conclusão

A API Temporal do JavaScript representa um avanço significativo no tratamento de datas e horas em JavaScript. Sua imutabilidade, API clara, suporte robusto a fusos horários e capacidades de sistemas de calendário a tornam uma ferramenta poderosa para desenvolvedores que constroem aplicações que precisam trabalhar com datas e horas de forma precisa e confiável em diversos contextos internacionais. Embora o suporte dos navegadores ainda esteja evoluindo, os benefícios da API Temporal fazem com que valha a pena aprender e adotá-la para novos projetos. Ao abraçar a API Temporal e seguir as melhores práticas de internacionalização, você pode criar aplicações que fornecem uma experiência de data e hora perfeita e precisa para usuários em todo o mundo.

Leitura Adicional