Logboekviewers, controletijdlijnen en telemetrie-UI's nemen vaak gebeurtenissen op waarvan de ISO 8601-tijdstempels met microseconde- of nanosecondeprecisie zijn vastgelegd door een server, database of systeemeigen klok (bijvoorbeeld 2026-04-01T12:00:00.000123456Z). Omdat het verouderde Date-object alleen milliseconden opslaat, worden cijfers van minder dan een milliseconde stilzwijgend afgekapt als die tekenreeksen worden geparseerd met new Date() of Date.parse(). Hierdoor botsen afzonderlijke gebeurtenissen binnen dezelfde milliseconde en worden ze in een onstabiele volgorde gesorteerd.
Temporal.Instant vertegenwoordigt een exact punt op de UTC-tijdlijn met een precisie van nanoseconden en zonder gekoppelde tijdzone. Als je vooraf opgenomen tijdstempels met hoge precisie parseert met Temporal.Instant.from(), blijft de volledige nanosecondewaarde behouden, wordt er deterministisch gesorteerd met Temporal.Instant.compare() en worden exacte Temporal.Duration-intervallen tussen gebeurtenissen berekend. In browsers wordt Temporal.Now.instant() opzettelijk beperkt tot milliseconden of microseconden om Spectre-timingaanvallen te beperken. Gebruik Temporal.Instant.from() om tijdstempels in nanoseconden te behouden die door externe klokken worden geproduceerd en gebruik performance.now() als je intervallen van minder dan een milliseconde lokaal in de client meet.
Implementeren
Zo parseert, sorteert en meet u intervallen tussen tijdstempels met hoge precisie:
- Geregistreerde tijdstempels parseren als
Temporal.Instant: GebruikTemporal.Instant.from(isoString)voor de tijdstempelreeks die wordt geleverd door de server, database of logregel. Behoud het tijdstempel dat de bron heeft geregistreerd. Vervang het niet doorTemporal.Now.instant()in de browser. - Gebeurtenissen chronologisch sorteren: Gebruik
Temporal.Instant.compare(a, b)als de vergelijker die wordt doorgegeven aanArray.prototype.sort()ofArray.prototype.toSorted(). De volledige nanosecondewaarde wordt vergeleken, zodat de volgorde van submilliseconden behouden blijft. - Intervallen berekenen: Gebruik
instant.since(previousInstant)om eenTemporal.Durationtussen opeenvolgende gebeurtenissen te krijgen. Gebruika.equals(b)om gebeurtenissen met identieke tijdstempels te detecteren. - Intervallen weergeven met
toLocaleString(): Maak deTemporal.Durationop voor gebruikers metduration.toLocaleString(), die delegeert naarIntl.DurationFormat. Converteer niet naar éénNumbervan nanoseconden voor weergave. - Serialiseren voor overdracht: Gebruik
Temporal.Instant.prototype.toString()om een standaard ISO 8601-tekenreeks te genereren (altijd in UTC met een achtervoegselZ).
Voorbeeldcode: Tijdstempels met hoge precisie sorteren
// 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));
Strategische implementatie en best practices
- Gebruik WEL
Temporal.Instant.from()om tijdstempels met hoge precisie te parseren die zijn geregistreerd op basis van één klok (zoals een server, database of logboekpipeline) die moeten worden geordend of gedifferentieerd. In tegenstelling totTemporal.PlainDateTimevertegenwoordigtTemporal.Instanteen ondubbelzinnig punt op de universele tijdlijn. - WEL het tijdstempel behouden dat door de bron is geregistreerd. In browsers wordt
Temporal.Now.instant()vastgezet op milliseconde-/microsecondeprecisie voor Spectre-timingaanvallen en mitigatie van fingerprinting. Gebruikperformance.now()/performance.mark()voor lokale clientintervallen van minder dan een milliseconde enTemporal.Instant.from()om nanoseconde-tijdstempels van server- of native klokken te parseren. - Gebruik WEL
Temporal.Instant.compare()voor sorteren ena.equals(b)voor gelijkheidscontroles. ControleerTemporal.Instant.compare(a, b) === 0niet en vergelijk de uitvoer van.toString()niet. - Parseer GEEN tekenreeksen met tijdstempels met hoge precisie met
new Date()ofDate.parse()voor ordening, omdat ze worden afgekapt tot milliseconden en botsingen veroorzaken. - Maak van een interval GEEN enkel getal voor weergave.
duration.total('nanoseconds')retourneert eenNumber, die hoger is danNumber.MAX_SAFE_INTEGERvoor perioden langer dan ongeveer 104 dagen en ongemerkt precisie verliest.epochNanoseconds(eenBigInt) aftrekken is exact, maar verwijdert de eenheidsstructuur. Houd intervallen alsTemporal.Durationen maak ze op met.toLocaleString(). - WEL: Converteer een
InstantnaarTemporal.ZonedDateTimemetinstant.toZonedDateTimeISO(timeZone)als je de gelokaliseerde kloktijd van een gebeurtenis aan een gebruiker wilt tonen.
Reservestrategie
Fallbacks en browserondersteuning voor Temporal
Voor browsers die de native Temporal API nog niet ondersteunen, gebruik je functiedetectie en laad je temporal-polyfill dynamisch (~15 KB min+gz).
Houd er rekening mee dat als je temporal-polyfill importeert, het Temporal-object niet automatisch wordt toegewezen aan het globale bereik. Wijs de waarde expliciet toe als je code afhankelijk is van 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();
})();