Loganzeigen, Audit-Zeitachsen und Telemetrie-UIs erfassen häufig Ereignisse, deren ISO 8601-Zeitstempel von einem Server, einer Datenbank oder einer nativen Uhr mit Mikrosekunden- oder Nanosekundenpräzision aufgezeichnet wurden (z. B. 2026-04-01T12:00:00.000123456Z). Da das Legacy-Objekt Date nur Millisekunden speichert, werden beim Parsen dieser Strings mit new Date() oder Date.parse() Ziffern unter einer Millisekunde stillschweigend abgeschnitten. Dies führt dazu, dass unterschiedliche Ereignisse innerhalb derselben Millisekunde kollidieren und in einer instabilen Reihenfolge sortiert werden.
Temporal.Instant stellt einen genauen Zeitpunkt auf der UTC-Zeitachse mit Nanosekunden-Genauigkeit und ohne angehängte Zeitzone dar. Beim Parsen von vorab aufgezeichneten Zeitstempeln mit hoher Genauigkeit mit Temporal.Instant.from() wird der vollständige Nanosekundenwert beibehalten, deterministisch mit Temporal.Instant.compare() sortiert und genaue Temporal.Duration-Intervalle zwischen Ereignissen berechnet. Beachten Sie, dass Temporal.Now.instant() in Browsern absichtlich auf Millisekunden- oder Mikrosekundenauflösung beschränkt wird, um Spectre-Timing-Angriffe zu verhindern. Verwenden Sie Temporal.Instant.from(), um Nanosekunden-Zeitstempel von externen Uhren beizubehalten, und performance.now(), wenn Sie Intervalle im Submillisekundenbereich lokal im Client messen.
Implementierung
So parsen, sortieren und messen Sie Intervalle zwischen hochpräzisen Zeitstempeln:
- Aufgezeichnete Zeitstempel als
Temporal.Instantparsen: Verwenden SieTemporal.Instant.from(isoString)für den Zeitstempelstring, der vom Server, von der Datenbank oder von der Logzeile bereitgestellt wird. Behalten Sie den von der Quelle aufgezeichneten Zeitstempel bei und ersetzen Sie ihn im Browser nicht durchTemporal.Now.instant(). - Ereignisse chronologisch sortieren: Verwenden Sie
Temporal.Instant.compare(a, b)als Vergleichswert, der anArray.prototype.sort()oderArray.prototype.toSorted()übergeben wird. Der vollständige Nanosekundenwert wird verglichen, sodass die Reihenfolge im Submillisekundenbereich beibehalten wird. - Intervalle berechnen: Verwenden Sie
instant.since(previousInstant), um eineTemporal.Durationzwischen aufeinanderfolgenden Ereignissen zu erhalten. Verwenden Siea.equals(b), um Ereignisse mit identischen Zeitstempeln zu erkennen. - Intervalle mit
toLocaleString()anzeigen: Formatieren Sie dieTemporal.Durationfür Nutzer mitduration.toLocaleString(), wodurch die Formatierung anIntl.DurationFormatdelegiert wird. Konvertieren Sie sie nicht in einen einzelnenNumber-Wert von Nanosekunden für die Anzeige. - Für die Übertragung serialisieren: Verwenden Sie
Temporal.Instant.prototype.toString(), um einen Standard-ISO-8601-String auszugeben (immer in UTC mit dem SuffixZ).
Beispielcode: Hochpräzise Zeitstempel sortieren
// 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 Implementierung und Best Practices
- DO use
Temporal.Instant.from()for parsing high-precision timestamps recorded against a single clock (such as a server, database, or log pipeline) that need to be ordered or differenced. Im Gegensatz zuTemporal.PlainDateTimestelltTemporal.Instanteinen eindeutigen Punkt auf der universellen Zeitachse dar. - BEHALTEN Sie den von der Quelle aufgezeichneten Zeitstempel bei. In Browsern wird
Temporal.Now.instant()auf Millisekunden-/Mikrosekunden-Genauigkeit beschränkt, um Spectre-Timing-Angriffe und Fingerprinting zu verhindern. Verwenden Sieperformance.now()/performance.mark()für lokale Client-Intervalle im Submillisekundenbereich undTemporal.Instant.from(), um Nanosekunden-Zeitstempel von Server- oder nativen Uhren zu parsen. - DO: Verwenden Sie
Temporal.Instant.compare()zum Sortieren unda.equals(b)für Gleichheitsprüfungen. Prüfen Sie nichtTemporal.Instant.compare(a, b) === 0und vergleichen Sie nicht die Ausgabe von.toString(). - Parsen Sie Zeitstempelstrings mit hoher Genauigkeit NICHT mit
new Date()oderDate.parse(), um sie zu sortieren, da sie auf Millisekunden gekürzt werden und Kollisionen verursachen. - NICHT ein Intervall für die Anzeige auf eine einzelne Zahl reduzieren.
duration.total('nanoseconds')gibt einenNumberzurück, der bei Zeiträumen von mehr als etwa 104 TagenNumber.MAX_SAFE_INTEGERüberschreitet und unbemerkt an Genauigkeit verliert. Das Subtrahieren vonepochNanoseconds(einBigInt) ist genau, verwirft aber die Einheitenstruktur. Behalten Sie Intervalle alsTemporal.Durationbei und formatieren Sie sie mit.toLocaleString(). - EMPFOHLEN: Konvertieren Sie einen
Instantmitinstant.toZonedDateTimeISO(timeZone)in einenTemporal.ZonedDateTime, wenn Sie einem Nutzer die lokalisierte Uhrzeit eines Ereignisses anzeigen müssen.
Fallback-Strategie
Fallbacks und Browserunterstützung für Temporal
Für Browser, die die native Temporal API noch nicht unterstützen, können Sie die Funktionserkennung verwenden und temporal-polyfill dynamisch laden (~15 KB min+gz).
Beachten Sie, dass das Importieren von temporal-polyfill das Temporal-Objekt nicht automatisch dem globalen Bereich zuweist. Weisen Sie ihn explizit zu, wenn Ihr Code auf globalThis.Temporal basiert.
// 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();
})();