Etkinlikler arasında geçen veya kalan süreyi (ör. deneme süresinin sona ermesi, abonelik geri sayımları veya SLA pencereleri) hesaplamak ve bu süreleri yerelleştirilmiş, okunabilir bir biçimde sunmak için geçmişte manuel matematik veya harici kitaplıklar gerekiyordu. Eski Date nesnesi yalnızca milisaniye cinsinden zamanı izler. Bu nedenle takvim ayı aritmetiği, yaz saati uygulaması (DST) geçişleri ve birim dengeleme işlemleri hataya açık olur.
Temporal API'si, yaz saati uygulaması için güvenli zaman farkları, yapılandırılabilir birim dengeleme, takvime duyarlı süre karşılaştırmaları ve yerelleştirilmiş biçimlendirme sağlamak üzere Temporal.ZonedDateTime ile Temporal.Duration ve Intl.DurationFormat'yi eşleştirir.
Nasıl uygulanır?
Temporal.ZonedDateTimeuç noktalarını alma: Sistem saat dilimindeki geçerli saat içinTemporal.Now.zonedDateTimeISO()kullanın veya hedef etkinliğin saat dilimi kullanıcının sistem varsayılanından farklı olduğunda açık bir IANA saat dilimi dizesi (Temporal.Now.zonedDateTimeISO(timeZone)) iletin..since()ve.until()ile farkları hesaplama:- Geçmiş bir etkinlikten bu yana geçen süreyi hesaplamak için
now.since(start, options)işlevini kullanın. - Gelecekteki bir etkinliğe kadar kalan süreyi hesaplamak için
now.until(end, options)işlevini kullanın. - Elde edilen
Temporal.Durationdeğerini dengelemek ve yuvarlamak içinlargestUnit(ör.'year','month','day','hour') vesmallestUnit(ör.'minute') değerlerini iletin.
- Geçmiş bir etkinlikten bu yana geçen süreyi hesaplamak için
- Bağımsız
Temporal.Durationnesnelerini dengeleme veya karşılaştırma:Temporal.Duration.from({ minutes: 90 })ile bağımsız süreler oluşturun veduration.round({ largestUnit: 'hour' })ile birimleri yeniden dengeleyin (takvim ayları, yılları veya yaz saati geçişleri arasında dengeleme yaparkenrelativeTodeğerini sağlayın).- İki süreyi
Temporal.Duration.compare(d1, d2, { relativeTo })ile karşılaştırın. Sürelerden biri takvim birimleri (years,months,weeks) içeriyorsa veya yaz saati uygulaması sınırlarını aşıyorsarelativeToolarakPlainDateveyaZonedDateTimeiletmek gerekir.
- İnsanlar ve makineler için biçimlendirme:
- Yerelleştirilmiş, kullanıcılara yönelik metinler için
duration.toLocaleString(locale, options)(Intl.DurationFormatöğesine yetki verir) kullanın. duration.toString()özelliğini yalnızca makine tarafından okunabilen ISO 8601 süre dizeleri (ör.P1M2DT4H) için kullanın.
- Yerelleştirilmiş, kullanıcılara yönelik metinler için
Örnek: Deneme süresi sona erme farkı ve yerelleştirilmiş biçimlendirme
// 1. Get the current time in an explicit target IANA time zone (or omit the
// argument to use the system's current time zone).
const tz = 'America/New_York';
const now = Temporal.Now.zonedDateTimeISO(tz);
// 2. Combine separate date and time strings directly.
// Do not build an ISO string with template literals; chain Temporal methods instead.
const startDateStr = '2025-01-01';
const startTimeStr = '12:00:00';
const endDateStr = '2025-01-31';
const endTimeStr = '12:00:00';
const start = Temporal.PlainDate.from(startDateStr).toPlainDateTime(startTimeStr).toZonedDateTime(tz);
const end = Temporal.PlainDate.from(endDateStr).toPlainDateTime(endTimeStr).toZonedDateTime(tz);
// 3. Calculate differences using .since() and .until()
// ZonedDateTime differences default to largestUnit: 'hour' (days are not a fixed
// length across DST, so Temporal won't balance into days unless asked). Pass
// largestUnit: 'day' or a calendar unit ('week', 'month', 'year') when you want a
// human-scale breakdown instead of e.g. PT720H. smallestUnit rounds away
// seconds and sub-second noise so the formatted string stays readable.
const timeActive = now.since(start, { largestUnit: 'year', smallestUnit: 'minute' });
const timeRemaining = now.until(end, { largestUnit: 'year', smallestUnit: 'minute' });
// 4. Format durations for display with .toLocaleString() (Intl.DurationFormat)
// instead of manually concatenating unit numbers and suffixes. 'en-US' is used
// here for deterministic output; pass undefined to use the user's locale.
console.log(`Active: ${timeActive.toLocaleString('en-US', { style: 'narrow' })}`);
console.log(`Remaining: ${timeRemaining.toLocaleString('en-US', { style: 'long' })}`);
// Use .toString() for ISO 8601 serialization (e.g., API payloads or <time datetime="...">)
console.log(`ISO 8601: ${timeRemaining.toString()}`);
// 5. Check status via .sign, and compare durations with Temporal.Duration.compare()
const isExpired = timeRemaining.sign < 0;
// Pass relativeTo when comparing durations that may include calendar months/years or DST shifts
const isPastHalfway = Temporal.Duration.compare(timeActive, timeRemaining, { relativeTo: now }) > 0;
Örnek: Bağımsız Süreleri Dengeleme (round ve Intl.DurationFormat)
// Convert a raw unit count (e.g., 90 minutes) into a balanced breakdown (1 hour, 30 minutes)
const rawDuration = Temporal.Duration.from({ minutes: 90 });
const balanced = rawDuration.round({ largestUnit: 'hour' });
// Format via duration.toLocaleString() or directly with Intl.DurationFormat
const formatter = new Intl.DurationFormat('en-US', { style: 'long' });
console.log(formatter.format(balanced)); // "1 hour, 30 minutes"
Stratejik Uygulama ve En İyi Uygulamalar
- Belirli saat dilimlerinde gerçekleşen gerçek dünya etkinliklerini (ör. abonelik yenilemeleri veya etkinlik geri sayımları) içeren hesaplamalar için
Temporal.ZonedDateTimeKULLANIN ve sistem varsayılanı dışında bir bölgeye göre hesaplama yaparkenTemporal.Now.zonedDateTimeISO(timeZone)için açık birtimeZoneiletin. `${dateStr}T${timeStr}`gibi bir ISO dizesini birleştirmek yerine, ayrı tarih ve saat dizelerini Temporal yöntemleriyle (ör.Temporal.PlainDate.from(dateStr).toPlainDateTime(timeStr).toZonedDateTime(tz)veyaTemporal.PlainDate.from(dateStr).toZonedDateTime({ timeZone: tz, plainTime: timeStr })) birleştirin (DO).- DO pass
largestUnit(e.g.'day','month','year') in.since(),.until(), or.round()when you want durations balanced beyond hours;ZonedDateTimedifference methods default to'hour'. - İki süreyi karşılaştırırken
Temporal.Duration.compare(d1, d2, { relativeTo })KULLANIN. Sürelerden biri takvim birimleri (months,years) veya saat dilimine duyarlı günler içeriyorsarelativeTosabitleyici sağlayın. ${duration.years}y ${duration.months}m...değerini manuel olarak eklemek yerineduration.toLocaleString()veyanew Intl.DurationFormat(locale, { style })('long','short','narrow'veya'digital') kullanarak süreleri kullanıcıya gösterilecek şekilde biçimlendirin (DO).duration.toString(), makine tarafından okunabilen ISO 8601 süre dizeleri (ör.PT1H30M) için KULLANILMALIDIR. Kullanıcılara yönelik metinlerde asla kullanılmamalıdır.PlainTimedeğeriniHH:MMolarak (ör.<input type="time">için) oluştururken dize.slice(0, 5)yerine.toPlainTime().toString({ smallestUnit: 'minute' })KULLANIN.- Örnekleri doğrudan DEĞİŞTİRMEYİN;
Temporalnesneleri değiştirilemez..add(),.subtract(),.round()veya.with()gibi işlemler yeni bir örnek döndürür. - Farkın kendisi için
Date/.getTime()aritmetiğine DÖNMEYİN;Date, saat dilimine duyarlı takvim matematiğine sahip değildir ve yalnızca milisaniye hassasiyetine sahiptir. - Bir sürenin geçmiş/süresi dolmuş bir zaman noktasını (
sign < 0) mı yoksa gelecekteki bekleyen bir başlangıcı mı temsil ettiğini kontrol etmek için hesaplananTemporal.Duration(veyaTemporal.ZonedDateTime.compare()) öğesinin yerel.signözelliğini KULLANIN.
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();
})();