Como coordenar eventos globais com o Temporal

Recursos da Web: Temporal

Programar eventos em diferentes fusos horários é notoriamente difícil com o objeto Date legado, especialmente em transições de horário de verão, quando as horas podem ser puladas ou repetidas.

A API Temporal fornece Temporal.ZonedDateTime para representar uma data e hora em um fuso horário específico, processando as transições de horário de verão de forma automática e previsível.

Como implementar

Para coordenar eventos globais e lidar com possíveis conflitos de horário de verão:

  1. OBRIGATÓRIO: criar um ZonedDateTime: use Temporal.ZonedDateTime.from() para criar um objeto de data e hora que reconhece o fuso horário.
  2. OBRIGATÓRIO: lidar com ambiguidade: use a opção disambiguation para controlar o comportamento quando um horário for ambíguo ou não existir (por exemplo, durante mudanças de horário).
  3. OBRIGATÓRIO: converter fusos horários: use .withTimeZone() para ver o horário equivalente em outro local.

Exemplo: programação e detecção de conflitos

// 1. Define the event time and target time zone
const date = "2025-03-09";
const time = "02:30"; // This time is skipped in New York during Spring Forward
const timeZone = "America/New_York";
const inputStr = `${date}T${time}[${timeZone}]`;

// 2. Detect conflicts using 'reject'
let hasConflict = false;
try {
  // 'reject' throws RangeError if the time is ambiguous or does not exist
  Temporal.ZonedDateTime.from(inputStr, { disambiguation: 'reject' });
} catch (e) {
  if (e instanceof RangeError) {
    hasConflict = true;
    console.log("This time falls in a DST transition gap or overlap.");
  }
}

// 3. Resolve the time safely using 'compatible' (default)
// 'compatible' will resolve to a valid time even if skipped or repeated
const hostTime = Temporal.ZonedDateTime.from(inputStr, { disambiguation: 'compatible' });
console.log(`Resolved time: ${hostTime.toString()}`);

// 4. Convert to another time zone (e.g., Tokyo)
const tokyoTime = hostTime.withTimeZone("Asia/Tokyo");
// Use toLocaleString() for user-facing display instead of manual hour/minute padding
console.log(`Tokyo time: ${tokyoTime.toLocaleString('en-US', { hour: 'numeric', minute: '2-digit' })}`);

Implementação estratégica e práticas recomendadas

  • USE Temporal.ZonedDateTime para eventos vinculados a uma localização geográfica específica (como uma reunião em uma cidade específica).
  • USE disambiguation: 'reject' se precisar detectar e avisar os usuários sobre conflitos de agendamento durante as transições do horário de verão.
  • USE disambiguation: 'compatible' (o padrão) quando quiser que o sistema escolha automaticamente um horário adequado quando houver conflitos.
  • NÃO use Temporal.PlainDateTime para eventos globais, porque ele não contém informações de fuso horário e não pode considerar mudanças de horário de verão.
  • USE .withTimeZone() para calcular o horário equivalente em outros locais sem alterar o objeto original (os objetos temporais são imutáveis).
  • RECOMENDAMOS usar a formatação nativa de .toLocaleString() (como { hour: 'numeric', minute: '2-digit' }) para exibições de tempo voltadas ao usuário, em vez de cálculos e preenchimentos manuais.

Estratégia de fallback

Substitutos e suporte do navegador para Temporal

Para navegadores que ainda não são compatíveis com a API Temporal nativa, use a detecção de recursos e carregue dinamicamente temporal-polyfill (~15 KB min+gz).

A importação de temporal-polyfill não atribui automaticamente o objeto Temporal ao escopo global. Atribua-o explicitamente se o código depender de globalThis.Temporal.

// Check if Temporal is supported natively
(async () => {
  if (typeof Temporal === 'undefined') {
    // Load the polyfill conditionally
    const module = await import('https://esm.sh/temporal-polyfill');
    globalThis.Temporal = module.Temporal;
    // Extend Date.prototype if needed
    Date.prototype.toTemporalInstant = module.toTemporalInstant;
  }
  initializeApp();
})();