Domine a API Temporal do JavaScript para manipulação moderna de data e hora. Aprenda a substituir os objetos Date legados por uma API poderosa, intuitiva e ciente de fusos horários.
API Temporal do JavaScript: Manipulação Moderna de Data e Hora
O objeto Date do JavaScript tem sido, há muito tempo, uma fonte de frustração para desenvolvedores. Sua mutabilidade, falta de suporte nativo a fusos horários e API desajeitada levaram a inúmeras bibliotecas e soluções alternativas. Felizmente, a API Temporal visa resolver essas deficiências, fornecendo uma solução moderna, intuitiva e ciente de fusos horários para a manipulação de data e hora em JavaScript.
O que é a API Temporal?
A API Temporal é um novo objeto global, Temporal, que fornece uma maneira moderna e padronizada de trabalhar com datas e horas em JavaScript. Ela foi projetada para substituir o objeto legado Date, oferecendo melhorias significativas em termos de design de API, imutabilidade, suporte a fusos horários e usabilidade geral. Faz parte de uma proposta do ECMAScript e está sendo implementada nos principais motores de JavaScript.
Principais benefícios da API Temporal:
- Imutabilidade: Objetos Temporal são imutáveis, o que significa que operações sobre eles retornam novos objetos em vez de modificar o original. Isso ajuda a prevenir efeitos colaterais inesperados e torna o código mais fácil de raciocinar.
- API Clara: A API foi projetada para ser mais intuitiva e consistente do que o objeto legado
Date. - Suporte a Fusos Horários: O Temporal oferece suporte robusto para fusos horários, permitindo trabalhar com datas e horas em diferentes locais ao redor do mundo.
- Suporte a Calendários: Além do calendário gregoriano, a API permite o uso de outros sistemas de calendário, facilitando aplicações globais.
- Tratamento de Segundos Bissextos: A API Temporal leva em conta os segundos bissextos, fornecendo cálculos de tempo mais precisos.
Começando com o Temporal
Embora a API Temporal ainda esteja em desenvolvimento e não seja totalmente suportada em todos os navegadores e ambientes Node.js, você pode usar um polyfill para começar a experimentá-la hoje. Você pode instalar o polyfill via npm:
npm install @js-temporal/polyfill
Depois, importe o polyfill no seu código JavaScript:
import { Temporal } from '@js-temporal/polyfill';
Uma vez que o polyfill esteja instalado, você pode começar a usar o objeto Temporal e suas várias classes.
Classes Principais do Temporal
A API Temporal fornece várias classes principais para trabalhar com datas e horas:
Temporal.PlainDate: Representa uma data de calendário (ano, mês e dia) sem qualquer informação de fuso horário ou hora do dia.Temporal.PlainTime: Representa uma hora do dia (hora, minuto, segundo e fração de segundo) sem qualquer informação de data ou fuso horário.Temporal.PlainDateTime: Representa uma data e hora sem qualquer informação de fuso horário.Temporal.ZonedDateTime: Representa uma data e hora com um fuso horário específico.Temporal.Instant: Representa um ponto específico no tempo, medido em nanossegundos desde a época Unix (1 de janeiro de 1970, às 00:00:00 Horário Universal Coordenado (UTC)).Temporal.TimeZone: Representa um fuso horário.Temporal.Duration: Representa uma duração de tempo, como horas, minutos ou segundos.Temporal.Now: Fornece acesso à data e hora atuais.
Trabalhando com PlainDate
A classe Temporal.PlainDate representa uma data sem qualquer informação de fuso horário ou hora do dia. É útil para representar aniversários, datas comemorativas ou outros eventos baseados em data.
Criando um PlainDate:
const plainDate = Temporal.PlainDate.from({ year: 2024, month: 10, day: 26 });
console.log(plainDate.toString()); // Saída: 2024-10-26
Você também pode criar um PlainDate a partir de uma string no formato ISO 8601:
const plainDateFromString = Temporal.PlainDate.from('2024-12-25');
console.log(plainDateFromString.toString()); // Saída: 2024-12-25
Acessando Componentes da Data:
const year = plainDate.year; // 2024
const month = plainDate.month; // 10
const day = plainDate.day; // 26
const dayOfWeek = plainDate.dayOfWeek; // Dia da semana (1-7, Segunda-Domingo)
const dayOfYear = plainDate.dayOfYear; // Dia do ano (1-366)
const daysInMonth = plainDate.daysInMonth; // Número de dias no mês
const isLeapYear = plainDate.isLeapYear; // Booleano indicando se o ano é bissexto
Adicionando e Subtraindo Dias:
const nextDay = plainDate.add({ days: 1 });
console.log(nextDay.toString()); // Saída: 2024-10-27
const previousWeek = plainDate.subtract({ weeks: 1 });
console.log(previousWeek.toString()); // Saída: 2024-10-19
Comparando Datas:
const anotherDate = Temporal.PlainDate.from({ year: 2024, month: 11, day: 15 });
if (plainDate.equals(anotherDate)) {
console.log('As datas são iguais');
} else if (plainDate.lessThan(anotherDate)) {
console.log('plainDate é anterior a anotherDate');
} else {
console.log('plainDate é posterior a anotherDate');
}
// Saída: plainDate é anterior a anotherDate
Trabalhando com PlainTime
A classe Temporal.PlainTime representa uma hora do dia sem qualquer informação de data ou fuso horário. É útil para representar horários de funcionamento, horários de reuniões ou outros eventos baseados em tempo.
Criando um PlainTime:
const plainTime = Temporal.PlainTime.from({ hour: 14, minute: 30, second: 0 });
console.log(plainTime.toString()); // Saída: 14:30:00
Você também pode criar um PlainTime a partir de uma string no formato ISO 8601:
const plainTimeFromString = Temporal.PlainTime.from('09:00:00');
console.log(plainTimeFromString.toString()); // Saída: 09:00:00
Acessando Componentes da Hora:
const hour = plainTime.hour; // 14
const minute = plainTime.minute; // 30
const second = plainTime.second; // 0
const millisecond = plainTime.millisecond; // 0
const microsecond = plainTime.microsecond; // 0
const nanosecond = plainTime.nanosecond; // 0
Adicionando e Subtraindo Tempo:
const laterTime = plainTime.add({ minutes: 15 });
console.log(laterTime.toString()); // Saída: 14:45:00
const earlierTime = plainTime.subtract({ hours: 1 });
console.log(earlierTime.toString()); // Saída: 13:30:00
Comparando Horas:
const anotherTime = Temporal.PlainTime.from({ hour: 15, minute: 0, second: 0 });
if (plainTime.equals(anotherTime)) {
console.log('As horas são iguais');
} else if (plainTime.lessThan(anotherTime)) {
console.log('plainTime é anterior a anotherTime');
} else {
console.log('plainTime é posterior a anotherTime');
}
// Saída: plainTime é anterior a anotherTime
Trabalhando com PlainDateTime
A classe Temporal.PlainDateTime representa uma data e hora sem qualquer informação de fuso horário. Ela combina a funcionalidade de PlainDate e PlainTime.
Criando um PlainDateTime:
const plainDateTime = Temporal.PlainDateTime.from({ year: 2024, month: 10, day: 26, hour: 14, minute: 30, second: 0 });
console.log(plainDateTime.toString()); // Saída: 2024-10-26T14:30:00
Você também pode criar um PlainDateTime a partir de uma string no formato ISO 8601:
const plainDateTimeFromString = Temporal.PlainDateTime.from('2024-12-25T09:00:00');
console.log(plainDateTimeFromString.toString()); // Saída: 2024-12-25T09:00:00
Acessando Componentes de Data e Hora:
const year = plainDateTime.year; // 2024
const month = plainDateTime.month; // 10
const day = plainDateTime.day; // 26
const hour = plainDateTime.hour; // 14
const minute = plainDateTime.minute; // 30
const second = plainDateTime.second; // 0
Adicionando e Subtraindo Datas e Horas:
const nextDayAndTime = plainDateTime.add({ days: 1, hours: 2 });
console.log(nextDayAndTime.toString()); // Saída: 2024-10-27T16:30:00
const previousWeekAndTime = plainDateTime.subtract({ weeks: 1, minutes: 30 });
console.log(previousWeekAndTime.toString()); // Saída: 2024-10-19T14:00:00
Convertendo para PlainDate e PlainTime:
const plainDateFromDateTime = plainDateTime.toPlainDate();
console.log(plainDateFromDateTime.toString()); // Saída: 2024-10-26
const plainTimeFromDateTime = plainDateTime.toPlainTime();
console.log(plainTimeFromDateTime.toString()); // Saída: 14:30:00
Trabalhando com ZonedDateTime
A classe Temporal.ZonedDateTime representa uma data e hora com um fuso horário específico. Isso é crucial para aplicações que precisam lidar com datas e horas em diferentes locais ao redor do mundo. Ao contrário do objeto legado Date, o Temporal oferece suporte nativo a fusos horários.
Criando um ZonedDateTime:
const zonedDateTime = Temporal.ZonedDateTime.from({ year: 2024, month: 10, day: 26, hour: 14, minute: 30, second: 0, timeZone: 'America/Los_Angeles' });
console.log(zonedDateTime.toString()); // Saída: 2024-10-26T14:30:00-07:00[America/Los_Angeles]
Você também pode criar um ZonedDateTime a partir de um Instant e um fuso horário:
const instant = Temporal.Instant.fromEpochSeconds(1666785000); // Exemplo de timestamp
const zonedDateTimeFromInstant = instant.toZonedDateTimeISO('Europe/London');
console.log(zonedDateTimeFromInstant.toString()); // A saída irá variar com base no instante real, mas refletirá a data/hora em Europe/London
Acessando Componentes de Data e Hora:
const year = zonedDateTime.year; // 2024
const month = zonedDateTime.month; // 10
const day = zonedDateTime.day; // 26
const hour = zonedDateTime.hour; // 14
const minute = zonedDateTime.minute; // 30
const second = zonedDateTime.second; // 0
const timeZone = zonedDateTime.timeZone; // Objeto Temporal.TimeZone
Convertendo Entre Fusos Horários:
const newYorkDateTime = zonedDateTime.withTimeZone('America/New_York');
console.log(newYorkDateTime.toString()); // Saída: 2024-10-26T17:30:00-04:00[America/New_York]
Lidando com o Horário de Verão (DST):
O Temporal lida automaticamente com as transições de horário de verão (DST). Ao adicionar ou subtrair tempo, ele leva o DST em consideração, garantindo resultados precisos. Por exemplo, considere uma reunião agendada durante a transição do DST na Alemanha:
const meetingStart = Temporal.ZonedDateTime.from({ year: 2024, month: 3, day: 31, hour: 2, minute: 30, timeZone: 'Europe/Berlin' });
const meetingEnd = meetingStart.add({ hours: 1 }); // Adicionando 1 hora
console.log(meetingEnd.toString()); // Saída: 2024-03-31T03:30:00+02:00[Europe/Berlin]. Note que o offset muda devido ao DST
Trabalhando com Instant
A classe Temporal.Instant representa um ponto específico no tempo, medido em nanossegundos desde a época Unix. É útil para armazenar e comparar momentos exatos no tempo.
Criando um Instant:
const instant = Temporal.Instant.fromEpochSeconds(1666785000); // Exemplo de timestamp Unix em segundos
console.log(instant.toString()); // A saída será uma representação em string ISO daquele instante
Convertendo para ZonedDateTime:
const zonedDateTimeFromInstant = instant.toZonedDateTimeISO('America/Los_Angeles');
console.log(zonedDateTimeFromInstant.toString()); // Saída: Data e hora em America/Los_Angeles correspondente ao instante
Comparando Instantes:
const anotherInstant = Temporal.Instant.fromEpochSeconds(1666790000);
if (instant.equals(anotherInstant)) {
console.log('Os instantes são iguais');
} else if (instant.lessThan(anotherInstant)) {
console.log('instant é anterior a anotherInstant');
} else {
console.log('instant é posterior a anotherInstant');
}
// Saída: instant é anterior a anotherInstant
Trabalhando com Duração
A classe Temporal.Duration representa uma duração de tempo, como horas, minutos ou segundos. É útil para calcular a diferença entre duas datas ou horas.
Criando uma Duration:
const duration = Temporal.Duration.from({ hours: 2, minutes: 30 });
console.log(duration.toString()); // Saída: PT2H30M
Calculando a Diferença Entre Datas/Horas:
const startDate = Temporal.PlainDateTime.from({ year: 2024, month: 1, day: 1, hour: 0, minute: 0, second: 0 });
const endDate = Temporal.PlainDateTime.from({ year: 2024, month: 1, day: 3, hour: 12, minute: 30, second: 0 });
const difference = endDate.since(startDate);
console.log(difference.toString()); // Saída: P2DT12H30M
// Acessando os componentes da duração
console.log(difference.days); // 2
console.log(difference.hours); // 12
console.log(difference.minutes); // 30
Adicionando Duração a Datas/Horas:
const newDate = startDate.add(duration);
console.log(newDate.toString()); // Saída: 2024-01-03T02:30:00
Trabalhando com Calendários
A API Temporal suporta diferentes sistemas de calendário além do calendário gregoriano. Embora ainda não esteja totalmente implementado em todos os polyfills e motores, a intenção é permitir que as aplicações lidem com datas em calendários específicos de várias culturas. Por exemplo, para usar o calendário japonês (hipoteticamente, pois a implementação ainda está evoluindo):
// Este é um exemplo conceitual, pois o suporte a calendários ainda está em desenvolvimento
// const japaneseDate = Temporal.PlainDate.from({ year: 2024, month: 10, day: 26, calendar: 'japanese' });
// console.log(japaneseDate.toString()); // Esperado: Saída formatada de acordo com o calendário japonês
Nota: O suporte a calendários é uma funcionalidade em evolução da API Temporal, e a funcionalidade completa ainda não está universalmente disponível.
Exemplos Práticos e Casos de Uso
A API Temporal oferece uma vasta gama de possibilidades para lidar com datas e horas em JavaScript. Aqui estão alguns exemplos práticos e casos de uso:
- Agendamento de Compromissos: Crie uma aplicação de agendamento que permita aos usuários marcar compromissos em seu fuso horário local. O Temporal.ZonedDateTime facilita a conversão entre fusos horários e lida com as transições de DST. Para uma clínica em Berlim agendando compromissos globalmente:
- Cálculo de Idade: Determine a idade de um usuário com base em sua data de nascimento. O PlainDate permite que você represente a data de nascimento sem qualquer informação de fuso horário.
- Exibição de Datas e Horas em Diferentes Formatos: Formate datas e horas de acordo com a localidade do usuário. Embora os recursos de internacionalização (Intl) sejam separados, os objetos Temporal podem ser facilmente formatados usando
toLocaleString()ou métodos semelhantes quando combinados com os recursos da API Intl. - Rastreamento da Duração de Eventos: Calcule a duração de um evento e exiba-a em um formato legível por humanos. A Duração permite que você represente a diferença de tempo entre duas datas ou horas.
const appointmentTimeBerlin = Temporal.ZonedDateTime.from({ year: 2024, month: 11, day: 5, hour: 10, minute: 0, timeZone: 'Europe/Berlin' });
const appointmentTimeLA = appointmentTimeBerlin.withTimeZone('America/Los_Angeles');
console.log(`Horário do compromisso em Berlim: ${appointmentTimeBerlin.toString()}`);
console.log(`Horário do compromisso em Los Angeles: ${appointmentTimeLA.toString()}`);
const birthDate = Temporal.PlainDate.from({ year: 1990, month: 5, day: 15 });
const today = Temporal.Now.plainDateISO();
const age = today.year - birthDate.year - (today.month < birthDate.month || (today.month === birthDate.month && today.day < birthDate.day) ? 1 : 0);
console.log(`Idade: ${age}`);
const zonedDateTimeNow = Temporal.Now.zonedDateTimeISO('en-GB');
console.log(zonedDateTimeNow.toLocaleString('pt-BR'));
console.log(zonedDateTimeNow.toLocaleString('de-DE'));
const eventStart = Temporal.Instant.fromEpochSeconds(1700000000); // Exemplo de timestamp de início
const eventEnd = Temporal.Instant.fromEpochSeconds(1700005000); // Exemplo de timestamp de fim
const durationOfEvent = eventEnd.since(eventStart);
console.log(`Duração do evento: ${durationOfEvent.minutes} minutos`);
Melhores Práticas para Usar a API Temporal
Aqui estão algumas melhores práticas a ter em mente ao usar a API Temporal:
- Use a Imutabilidade: Adote a imutabilidade dos objetos Temporal. Evite modificar objetos diretamente. Em vez disso, crie novos objetos usando métodos como
add,subtractewith. - Lide com Fusos Horários Cuidadosamente: Esteja atento aos fusos horários ao trabalhar com datas e horas. Use
ZonedDateTimequando precisar representar datas e horas em um fuso horário específico. - Use Nomes de Variáveis Claros: Use nomes de variáveis descritivos que indiquem claramente o tipo de objeto Temporal que está sendo usado (por exemplo,
plainDate,zonedDateTime,duration). - Considere Polyfills: Como o Temporal ainda é relativamente novo, garanta suporte suficiente usando uma biblioteca de polyfill onde necessário.
- Valide a Entrada: Sempre valide a entrada do usuário para garantir que as datas e horas estejam no formato correto.
Migração do Date Legado
Migrar do objeto legado Date pode ser um processo gradual. Considere estas estratégias:
- Adoção Incremental: Comece usando o Temporal em novo código enquanto mantém o
Datenas partes existentes de sua aplicação. - Funções de Encapsulamento (Wrapper): Crie funções de encapsulamento que convertam entre objetos
Datee Temporal para facilitar a interoperabilidade durante a migração. - Testes Completos: Teste a migração extensivamente para garantir que todos os cálculos de data e hora sejam precisos.
API Temporal vs. Moment.js
O Moment.js foi uma biblioteca popular para manipulação de data e hora em JavaScript, mas agora é considerado um projeto legado e está em modo de manutenção. A API Temporal oferece uma solução mais moderna e padronizada que aborda muitas das deficiências do Moment.js. O Moment.js é mutável e não possui suporte nativo a fusos horários. A API Temporal é imutável e tem suporte nativo a fusos horários.
Conclusão
A API Temporal do JavaScript representa uma melhoria significativa em relação ao objeto legado Date. Sua imutabilidade, API clara, suporte a fusos horários e suporte a calendários a tornam uma ferramenta poderosa para lidar com datas e horas em aplicações JavaScript modernas. Embora a adoção ainda esteja crescendo, o uso de um polyfill permite que você comece a aproveitar seus benefícios hoje. À medida que a API se torna mais amplamente suportada, espera-se que se torne a maneira padrão de trabalhar com datas e horas em JavaScript.
Adote a API Temporal e desbloqueie uma maneira mais eficiente e confiável de gerenciar datas e horas em seus projetos, garantindo que sua aplicação lide com fusos horários globais e cálculos com precisão.