Het traditionele JavaScript-object Date is gebaseerd op een proleptische Gregoriaanse kalender. Hierdoor is het lastig om apps te maken voor gebruikers die andere kalendersystemen gebruiken, zoals de islamitische (maan), Hebreeuwse (lunisolar) of Chinese (lunisolar) kalender. Ontwikkelaars moesten eerder vertrouwen op complexe bibliotheken van derden of handmatige berekeningen om deze systemen te ondersteunen.
De Temporal API biedt eersteklas ondersteuning voor meerdere agendasystemen. Door een agenda-ID aan datumobjecten te koppelen, verwerkt Temporal de complexe berekeningen en opmaak die vereist zijn voor verschillende culturele contexten.
Implementeren
Zo ondersteun je wereldwijde agendasystemen met Temporal:
- Een kalender koppelen (verplicht): Als je een Temporal-object (zoals
Temporal.PlainDate) maakt of converteert, moet je het gewenste kalendersysteem opgeven metwithCalendar()om kalendergevoelige bewerkingen uit te voeren. - Gebruik stabiele ID's (verplicht voor lunisolaire kalenders): Gebruik
monthCodein plaats van de numerieke indexmonthom specifieke maanden in verschillende jaren in lunisolaire kalenders te identificeren. Gebruik dit alleen voor kalenders die schrikkelmaanden gebruiken, zoals de Hebreeuwse en Chinese kalenders. - Respecteer kalenderinvarianten (verplicht): Als je maanden of dagen doorloopt, mag je niet uitgaan van vaste waarden (zoals 12 maanden in een jaar of 31 dagen in een maand). Gebruik property's zoals
monthsInYearendaysInMonthom te zorgen dat je code werkt in alle agenda's. - Gebruik kalenderbewuste vergelijkingen (verplicht): Als je datums binnen een specifiek kalendersysteem vergelijkt, moet je
Temporal.PlainDate.compare()gebruiken in plaats van de eigenschappen jaar/maand/dag handmatig te vergelijken. Zo wordt de chronologische volgorde binnen de agendaregels correct verwerkt.
Voorbeeldcode: Agenda's converteren en herhalen
// 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'
});
Strategische implementatie en best practices
- Gebruik WEL
monthsInYearals de bovengrens als u door maanden loopt, in plaats van uit te gaan van 12. - Gebruik WEL
monthCodeom specifieke maanden te identificeren in kalenders die schrikkelmaanden gebruiken (bijvoorbeeld de Hebreeuwse of Chinese kalender), ongeacht het jaar. - Ga er NIET van uit dat
date.month === 12de laatste maand van het jaar is. Gebruikdate.month === date.monthsInYear. - Ga er NIET van uit dat
inLeapYear === trueimpliceert dat het jaar maar één dag langer is. In lunisolaire kalenders kan een hele schrikkelmaand worden toegevoegd. - Gebruik WEL
Temporal.PlainDate.compare()als je 2 datums in een specifiek agendasysteem vergelijkt in plaats van de eigenschappen Jaar/Maand/Dag handmatig te vergelijken. - Gebruik WEL
toLocaleString()om datums voor gebruikers op te maken in plaats van handmatige tekenreekssamenvoeging. - WEL: Controleer of het doelagendasysteem wordt ondersteund door de omgeving met
Intl.supportedValuesOf('calendar')voordat je agendaspecifieke Temporal-objecten maakt. - WEL: Houd er rekening mee dat sommige kalenders (zoals varianten van de islamitische kalender) afhankelijk zijn van visuele observatie in plaats van vaste berekeningen. De
TemporalAPI volgt deIntl-implementatie van de omgeving, die meestal berekende benaderingen gebruikt. Voor belangrijke culturele of religieuze datumberekeningen kun je het beste contact opnemen met domeinexperts of gespecialiseerde bibliotheken gebruiken. - WEL: Houd rekening met tijdperknamen als je agenda's gebruikt die tijdperken gebruiken (bijvoorbeeld de Japanse of boeddhistische agenda) door
toLocaleString()te gebruiken.
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();
})();