Os visualizadores de registros, as linhas do tempo de auditoria e as interfaces de telemetria geralmente ingerem eventos com carimbos de data/hora ISO 8601 registrados com precisão de microssegundos ou nanossegundos por um servidor, banco de dados ou relógio nativo (por exemplo, 2026-04-01T12:00:00.000123456Z). Como o objeto Date legado armazena apenas milissegundos, a análise dessas strings com new Date() ou Date.parse() trunca silenciosamente os dígitos de submilisegundos, fazendo com que eventos distintos no mesmo milissegundo colidam e sejam classificados em uma ordem instável.
Temporal.Instant representa um ponto exato na linha do tempo UTC com precisão de nanossegundos e sem fuso horário anexado. Ao analisar carimbos de data/hora de alta precisão pré-gravados com Temporal.Instant.from(), ele preserva o valor total de nanossegundos, classifica de forma determinística com Temporal.Instant.compare() e calcula intervalos exatos de Temporal.Duration entre eventos. Nos navegadores, Temporal.Now.instant() é deliberadamente limitado à resolução de milissegundos ou microssegundos para mitigar ataques de temporização do Spectre. Use Temporal.Instant.from() para preservar os carimbos de data/hora em nanossegundos produzidos por relógios externos e use performance.now() ao medir intervalos de submilisegundos localmente no cliente.
Como implementar
Para analisar, classificar e medir intervalos entre carimbos de data/hora de alta precisão:
- Analisar carimbos de data/hora registrados como
Temporal.Instant: useTemporal.Instant.from(isoString)na string de carimbo de data/hora fornecida pelo servidor, banco de dados ou linha de registro. Mantenha o carimbo de data/hora registrado pela origem. Não o substitua porTemporal.Now.instant()no navegador. - Classificar eventos cronologicamente: use
Temporal.Instant.compare(a, b)como o comparador transmitido paraArray.prototype.sort()ouArray.prototype.toSorted(). Ele compara o valor total em nanossegundos para que a ordem de submilissegundos seja preservada. - Calcular intervalos: use
instant.since(previousInstant)para receber umTemporal.Durationentre eventos consecutivos. Usea.equals(b)para detectar eventos com carimbos de data/hora idênticos. - Mostrar intervalos com
toLocaleString(): formate oTemporal.Durationpara usuários comduration.toLocaleString(), que delega paraIntl.DurationFormat. Não converta em um únicoNumberde nanossegundos para exibição. - Serializar para transmissão: use
Temporal.Instant.prototype.toString()para emitir uma string padrão ISO 8601 (sempre em UTC com um sufixoZ).
Exemplo de código: como classificar carimbos de data/hora de alta precisão
// Events received with nanosecond-precision ISO 8601 timestamps.
const rawEvents = [
{ nodeId: 'api-2', eventType: 'db.query', ts: '2026-04-01T12:00:00.000123456Z' },
{ nodeId: 'api-1', eventType: 'request.start', ts: '2026-04-01T12:00:00.000120000Z' },
{ nodeId: 'api-2', eventType: 'request.end', ts: '2026-04-01T12:00:00.000987654Z' },
];
// 1. Parse recorded timestamps as Temporal.Instant (never `new Date(ts)`,
// which drops everything below the millisecond).
const events = rawEvents.map(evt => ({
...evt,
timestamp: Temporal.Instant.from(evt.ts),
}));
// 2. Sort chronologically with the static compare() method
function sequenceEvents(items) {
// Instant.compare returns -1, 0, or 1, which is what sort() expects.
return [...items].sort((a, b) => Temporal.Instant.compare(a.timestamp, b.timestamp));
}
// 3. Calculate and display the interval between consecutive events
function analyzeTrace(sortedEvents) {
for (let i = 1; i < sortedEvents.length; i++) {
const prev = sortedEvents[i - 1];
const curr = sortedEvents[i];
// since() returns a Temporal.Duration that retains nanosecond precision.
const gap = curr.timestamp.since(prev.timestamp);
// 4. toLocaleString() formats the duration for people (e.g., "3μs 456ns").
// Avoid gap.total('nanoseconds'): spans over ~104 days exceed Number.MAX_SAFE_INTEGER.
// 'en-US' is used here for deterministic output; pass undefined to use the user's locale.
console.log(`${prev.eventType} → ${curr.eventType}: ${gap.toLocaleString('en-US', { style: 'narrow' })}`);
}
}
analyzeTrace(sequenceEvents(events));
Implementação estratégica e práticas recomendadas
- USE
Temporal.Instant.from()para analisar carimbos de data/hora de alta precisão registrados em um único relógio (como um servidor, banco de dados ou pipeline de registro) que precisam ser ordenados ou diferenciados. Ao contrário deTemporal.PlainDateTime,Temporal.Instantrepresenta um ponto inequívoco na linha do tempo universal. - MANTENHA o carimbo de data/hora registrado pela origem. Em navegadores,
Temporal.Now.instant()é fixado na precisão de milissegundos/microssegundos para mitigação de ataques de temporização Spectre e de impressões digitais. Useperformance.now()/performance.mark()para intervalos de clientes locais de submilisegundos eTemporal.Instant.from()para analisar carimbos de data/hora de nanossegundos de servidores ou relógios nativos. - USE
Temporal.Instant.compare()para classificação ea.equals(b)para verificações de igualdade. Não verifiqueTemporal.Instant.compare(a, b) === 0nem compare a saída de.toString(). - NÃO analise strings de carimbo de data/hora de alta precisão com
new Date()ouDate.parse()para ordenação, porque elas são truncadas em milissegundos e produzem colisões. - NÃO reduza um intervalo a um único número para exibição.
duration.total('nanoseconds')retorna umNumber, que excedeNumber.MAX_SAFE_INTEGERpara períodos maiores que ~104 dias e perde precisão silenciosamente. SubtrairepochNanoseconds(umBigInt) é exato, mas descarta a estrutura da unidade. Mantenha os intervalos comoTemporal.Duratione formate-os com.toLocaleString(). - É RECOMENDÁVEL converter um
InstantemTemporal.ZonedDateTimecominstant.toZonedDateTimeISO(timeZone)quando você precisar mostrar ao usuário o horário localizado de um evento.
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();
})();