Temporal.Instant ile yüksek hassasiyetli zaman damgalarını sıralama

Web özellikleri: Temporal

Günlük görüntüleyiciler, denetleme zaman çizelgeleri ve telemetri kullanıcı arayüzleri genellikle ISO 8601 zaman damgaları bir sunucu, veritabanı veya yerel saat tarafından mikrosaniye ya da nanosaniye hassasiyetinde kaydedilen etkinlikleri alır (örneğin, 2026-04-01T12:00:00.000123456Z). Eski Date nesnesi yalnızca milisaniyeleri depoladığından, bu dizeleri new Date() veya Date.parse() ile ayrıştırmak, milisaniyenin altındaki basamakları sessizce keser. Bu da aynı milisaniye içindeki farklı etkinliklerin çakışmasına ve kararsız bir sırada sıralanmasına neden olur.

Temporal.Instant, UTC zaman çizelgesinde nanosaniye hassasiyetinde ve ekli saat dilimi olmayan tam bir noktayı temsil eder. Temporal.Instant.from() ile önceden kaydedilmiş yüksek hassasiyetli zaman damgalarını ayrıştırırken tam nanosaniye değerini korur, Temporal.Instant.compare() ile kesin olarak sıralar ve etkinlikler arasındaki tam Temporal.Duration aralıklarını hesaplar. Tarayıcılarda Temporal.Now.instant(), Spectre zamanlama saldırısını azaltmak için kasıtlı olarak milisaniye veya mikrosaniye çözünürlüğüne sabitlenir. Harici saatler tarafından üretilen nanosaniye zaman damgalarını korumak için Temporal.Instant.from(), istemcide milisaniyenin altındaki aralıkları yerel olarak ölçerken performance.now() kullanın.

Nasıl uygulanır?

Yüksek hassasiyetli zaman damgaları arasındaki aralıkları ayrıştırmak, sıralamak ve ölçmek için:

  1. Kayıtlı zaman damgalarını Temporal.Instant olarak ayrıştır: Sunucu, veritabanı veya günlük satırı tarafından sağlanan zaman damgası dizesinde Temporal.Instant.from(isoString) kullanın. Kaynağın kaydettiği zaman damgasını koruyun. Tarayıcıda Temporal.Now.instant() ile değiştirmeyin.
  2. Etkinlikleri kronolojik olarak sıralama: Array.prototype.sort() veya Array.prototype.toSorted() işlevine iletilen karşılaştırıcı olarak Temporal.Instant.compare(a, b) kullanın. Tam nanosaniye değerini karşılaştırır, böylece milisaniye altı sıralama korunur.
  3. Aralıkları hesaplama: Ardışık etkinlikler arasında Temporal.Duration elde etmek için instant.since(previousInstant) kullanın. Aynı zaman damgalarına sahip etkinlikleri tespit etmek için a.equals(b) kullanın.
  4. Aralıkları toLocaleString() ile göster: Temporal.Duration değerini, Intl.DurationFormat değerine yetki veren duration.toLocaleString() ile kullanıcılar için biçimlendirin. Görüntüleme için tek bir nanosaniye Number değerine dönüştürmeyin.
  5. İletim için serileştirme: Standart bir ISO 8601 dizesi (her zaman Z son ekiyle UTC'de) oluşturmak için Temporal.Instant.prototype.toString() kullanın.

Örnek Kod: Yüksek Hassasiyetli Zaman Damgalarını Sıralama

// 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));

Stratejik Uygulama ve En İyi Uygulamalar

  • Sıralanması veya farkının alınması gereken tek bir saate (sunucu, veritabanı veya günlük ardışık düzeni gibi) göre kaydedilen yüksek hassasiyetli zaman damgalarını ayrıştırmak için Temporal.Instant.from() KULLANIN. Temporal.PlainDateTime değerinin aksine Temporal.Instant, evrensel zaman çizelgesinde net bir noktayı temsil eder.
  • Kaynak tarafından kaydedilen zaman damgasını KORUYUN. Tarayıcılarda Temporal.Now.instant(), Spectre zamanlama saldırısı ve parmak izi azaltma için milisaniye/mikrosaniye hassasiyetine sabitlenir. Milisaniye altı yerel istemci aralıkları için performance.now() / performance.mark(), sunucudan veya yerel saatlerden nanosaniye zaman damgalarını ayrıştırmak için Temporal.Instant.from() kullanın.
  • Sıralama için Temporal.Instant.compare(), eşitlik kontrolleri için a.equals(b) KULLANIN; Temporal.Instant.compare(a, b) === 0 çıkışını kontrol etmeyin veya .toString() çıkışını karşılaştırmayın.
  • Sıralama için yüksek hassasiyetli zaman damgası dizelerini new Date() veya Date.parse() ile ayrıştırmayın. Bu yöntem, dizeleri milisaniyeye kısaltır ve çakışmalara neden olur.
  • Aralığı, görüntüleme için tek bir sayıya DARALTMAMANIZ gerekir. duration.total('nanoseconds'), ~104 günden uzun süreler için Number.MAX_SAFE_INTEGER değerini aşan bir Number döndürür ve hassasiyeti sessizce kaybeder. epochNanoseconds (BigInt) değerini çıkarmak tam sonuç verir ancak birim yapısını siler. Aralıkları Temporal.Duration olarak tutun ve .toLocaleString() ile biçimlendirin.
  • Bir etkinliğin yerelleştirilmiş duvar saati zamanını kullanıcıya göstermeniz gerektiğinde instant.toZonedDateTimeISO(timeZone) ile Instant değerini Temporal.ZonedDateTime değerine DÖNÜŞTÜRÜN.

Yedek strateji

Temporal için yedekler ve tarayıcı desteği

Yerel Temporal API'yi henüz desteklemeyen tarayıcılar için özellik algılamayı kullanın ve temporal-polyfill'yi dinamik olarak yükleyin (~15 KB min+gz).

temporal-polyfill öğesini içe aktarmanın, Temporal nesnesini otomatik olarak global kapsama atamadığını unutmayın. Kodunuz globalThis.Temporal değerine bağlıysa bunu açıkça atayın.

// 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();
})();