Temporal ile Küresel Takvim Sistemlerini Destekleme

Web özellikleri: Temporal

Geleneksel JavaScript Date nesnesi, proleptik Gregoryen takvimini temel alır. Bu nedenle, İslam (ay), İbrani (ay-güneş) veya Çin (ay-güneş) takvimleri gibi diğer takvim sistemlerini kullanan kullanıcılar için uygulama geliştirmek zor olabilir. Geliştiriciler daha önce bu sistemleri desteklemek için karmaşık üçüncü taraf kitaplıklarına veya manuel hesaplamalara güvenmek zorundaydı.

Temporal API, birden fazla takvim sistemi için birinci sınıf destek sağlar. Temporal, takvim tanımlayıcılarını tarih nesneleriyle ilişkilendirerek farklı kültürel bağlamlar için gereken karmaşık aritmetik ve biçimlendirme işlemlerini yerel olarak gerçekleştirir.

Nasıl uygulanır?

Temporal kullanarak global takvim sistemlerini desteklemek için:

  1. Takvim ilişkilendirme (Zorunlu): Bir Temporal nesnesi (ör. Temporal.PlainDate) oluştururken veya dönüştürürken takvime duyarlı işlemler gerçekleştirmek için withCalendar() kullanarak istediğiniz takvim sistemini belirtmeniz gerekir.
  2. Sabit tanımlayıcılar kullanın (ay-güneş takvimleri için zorunludur): Ay-güneş takvimlerinde yıllar içindeki belirli ayları tanımlamak için sayısal month dizini yerine monthCode kullanmanız gerekir. Bu seçeneği yalnızca İbrani ve Çin takvimleri gibi artık ay kullanan takvimler için kullanın.
  3. Takvim Değişmezlerine Uyma (Zorunlu): Ayları veya günleri yinelerken sabit değerler (ör. bir yılda 12 ay veya bir ayda 31 gün) varsaymamalısınız. Kodunuzun tüm takvimlerde çalıştığından emin olmak için monthsInYear ve daysInMonth gibi özellikleri kullanın.
  4. Takvime Duyarlı Karşılaştırmalar Kullanın (Zorunlu): Belirli bir takvim sistemindeki tarihleri karşılaştırırken yıl/ay/gün özelliklerini manuel olarak karşılaştırmak yerine Temporal.PlainDate.compare() kullanmanız gerekir. Bu, takvim kuralları dahilinde kronolojik sıralamayı doğru şekilde işler.

Örnek Kod: Takvimleri Dönüştürme ve Yineleme

// 1. Helper to check calendar support
function isCalendarSupported(calendarId) {
  try {
    return Intl.supportedValuesOf('calendar').includes(calendarId);
  } catch {
    // Fallback for environments where supportedValuesOf is not available
    return false;
  }
}

// 2. Get current date in default ISO 8601 calendar
const isoDate = Temporal.Now.plainDateISO();

// 3. Convert to Hebrew calendar if supported
const calendarId = 'hebrew';
const targetDate = isCalendarSupported(calendarId) 
  ? isoDate.withCalendar(calendarId)
  : isoDate; // Fallback to ISO if not supported

if (targetDate.calendar.id !== calendarId) {
  console.warn(`Calendar ${calendarId} not supported; falling back to ISO 8601`);
}

// 4. Log properties specific to the calendar
console.log(`Calendar: ${targetDate.calendar.id}`);
console.log(`Year: ${targetDate.year}`);
console.log(`Month Code: ${targetDate.monthCode}`); // Stable across leap years

// 5. Safely iterate through months in the current year
for (let m = 1; m <= targetDate.monthsInYear; m++) {
  console.log(`Month ${m} has ${targetDate.with({ month: m }).daysInMonth} days.`);
}

// 6. Compare dates within the same calendar
const today = Temporal.Now.plainDateISO().withCalendar(calendarId);
const comparison = Temporal.PlainDate.compare(targetDate, today);
const relative = comparison < 0 ? 'Past' : comparison > 0 ? 'Future' : 'Today';
console.log(`Timeline: ${relative}`);

// 7. Format for display using toLocaleString (including era for era-based calendars like 'japanese')
const localizedDisplay = targetDate.toLocaleString('en-u-ca-hebrew', {
  day: 'numeric',
  month: 'long',
  year: 'numeric',
  era: 'long'
});

Stratejik Uygulama ve En İyi Uygulamalar

  • Aylar arasında döngü oluştururken 12'yi varsaymak yerine üst sınır olarak monthsInYear KULLANIN.
  • YAPIN: Yıldan bağımsız olarak artık ay kullanan takvimlerde (ör. İbrani veya Çin takvimi) belirli ayları tanımlamak için monthCode kullanın.
  • date.month === 12 ayının yılın son ayı olduğunu VARSAYMAYIN. date.month === date.monthsInYear kullanın.
  • inLeapYear === true ifadesinin, yılın yalnızca bir gün daha uzun olduğu anlamına geldiğini varsaymayın. Ay-güneş takvimlerinde tam bir artık ay ekleyebilir.
  • Yıl/Ay/Gün özelliklerini manuel olarak karşılaştırmak yerine belirli bir takvim sistemindeki iki tarihi karşılaştırırken Temporal.PlainDate.compare() KULLANIN.
  • Kullanıcılar için tarihleri biçimlendirirken manuel dize birleştirme yerine toLocaleString() KULLANIN.
  • Takvime özgü Temporal nesneleri oluşturmadan önce hedef takvim sisteminin Intl.supportedValuesOf('calendar') kullanan ortam tarafından desteklendiğini DO (DO) ile doğrulayın.
  • DO Bazı takvimlerin (ör. İslami takvimin varyantları) sabit hesaplamalar yerine görsel gözleme dayalı olabileceğini unutmayın. Temporal API'si, genellikle hesaplanan yaklaşımları kullanan ortamın Intl uygulamasını takip eder. Kültürel veya dini açıdan önemli tarih hesaplamaları için alan uzmanlarına danışın ya da özel kitaplıklar kullanın.
  • Dönemleri kullanan takvimleri (ör. Japon, Budist) kullanırken toLocaleString() kullanarak dönem adlarını HESABA KATIN.

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