האובייקט Date המסורתי ב-JavaScript מבוסס על לוח שנה גרגוריאני פרופלקטי, ולכן קשה ליצור אפליקציות למשתמשים שמסתמכים על מערכות אחרות של לוחות שנה, כמו לוח השנה המוסלמי (ירחי), העברי (ירחי-שמשי) או הסיני (ירחי-שמשי). בעבר, המפתחים היו צריכים להסתמך על ספריות מורכבות של צד שלישי או על חישובים ידניים כדי לתמוך במערכות האלה.
ה-API Temporal מספק תמיכה מעולה בכמה מערכות של לוחות שנה. כשמשייכים מזהה לוח שנה לאובייקטים של תאריכים, Temporal מטפל באופן מובנה בפעולות החשבון המורכבות ובפורמטים שנדרשים בהקשרים תרבותיים שונים.
איך להטמיע
כדי לתמוך במערכות יומנים גלובליות באמצעות Temporal:
- שיוך לוח שנה (חובה): כשיוצרים או ממירים אובייקט Temporal (כמו
Temporal.PlainDate), צריך לציין את מערכת לוח השנה הרצויה באמצעותwithCalendar()כדי לבצע פעולות שקשורות ללוח השנה. - שימוש במזהים קבועים (חובה בלוחות שנה ירחיים-שמשיים): צריך להשתמש ב-
monthCodeבמקום באינדקס המספריmonthכדי לזהות חודשים ספציפיים לאורך השנים בלוחות שנה ירחיים-שמשיים. האפשרות הזו מתאימה רק ליומנים שכוללים חודשים מעוברים, כמו לוח השנה העברי והסיני. - הקפדה על קבועים ביומן (חובה): כשעוברים על חודשים או ימים, אסור להניח ערכים קבועים (כמו 12 חודשים בשנה או 31 ימים בחודש). כדי לוודא שהקוד פועל בכל היומנים, צריך להשתמש במאפיינים כמו
monthsInYearו-daysInMonth. - שימוש בהשוואות שמותאמות ליומן (חובה): כשמשווים בין תאריכים במערכת יומן ספציפית, צריך להשתמש ב-
Temporal.PlainDate.compare()במקום להשוות באופן ידני בין מאפייני השנה, החודש והיום. כך הסדר הכרונולוגי מטופל בצורה נכונה במסגרת כללי היומן.
קוד לדוגמה: המרה ואיטרציה של יומנים
// 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'
});
הטמעה אסטרטגית ושיטות מומלצות
- מומלץ להשתמש ב-
monthsInYearכגבול העליון כשעוברים בלולאה על החודשים, במקום להניח שיש 12 חודשים. - מומלץ להשתמש ב-
monthCodeכדי לזהות חודשים ספציפיים ביומנים שכוללים חודשים מעוברים (למשל, עברי או סיני), בלי קשר לשנה. - אל תניחו ש-
date.month === 12הוא החודש האחרון בשנה. שימוש ב-date.month === date.monthsInYear. - אל תניחו ש-
inLeapYear === trueאומר שהשנה ארוכה יותר ביום אחד בלבד. בלוחות שנה שמבוססים על שנת הירח ושנת השמש, יכול להיות שיתווסף חודש מעובר שלם. - מומלץ להשתמש ב-
Temporal.PlainDate.compare()כשמשווים בין שני תאריכים במערכת לוח שנה ספציפית, במקום להשוות בין מאפייני שנה/חודש/יום באופן ידני. - מומלץ להשתמש ב-
toLocaleString()כדי לעצב תאריכים למשתמשים במקום שרשור מחרוזות ידני. - חשוב לוודא שמערכת היומן הרצויה נתמכת בסביבה באמצעות
Intl.supportedValuesOf('calendar')לפני שיוצרים אובייקטים זמניים ספציפיים ליומן. - חשוב לזכור שחלק מהלוחות (כמו גרסאות שונות של לוח השנה המוסלמי) עשויים להתבסס על תצפיות ויזואליות ולא על חישובים קבועים.
TemporalAPI פועל לפי ההטמעה שלIntlבסביבה, שבדרך כלל משתמשת בהערכות מחושבות. לחישובים קריטיים של תאריכים תרבותיים או דתיים, כדאי לאמת את התוצאות עם מומחים בתחום או להשתמש בספריות ייעודיות. - חשוב להביא בחשבון שמות של תקופות כשמשתמשים בלוחות שנה שכוללים תקופות (למשל, לוח השנה היפני או הבודהיסטי), באמצעות
toLocaleString().
אסטרטגיית גיבוי
תמיכה ב-Temporal בדפדפנים ופתרונות חלופיים
בדפדפנים שעדיין לא תומכים ב-API המקורי של Temporal, צריך להשתמש בזיהוי תכונות ולטעון באופן דינמי את temporal-polyfill (~15 KB min+gz).
חשוב לזכור שייבוא של temporal-polyfill לא מקצה באופן אוטומטי את האובייקט Temporal להיקף הגלובלי. אם הקוד שלכם מסתמך על 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();
})();