기존 JavaScript Date 객체는 선제적 그레고리력을 기반으로 하므로 이슬람력 (음력), 히브리력 (태음태양력), 중국력 (태음태양력)과 같은 다른 달력 시스템을 사용하는 사용자를 위한 애플리케이션을 빌드하기가 어렵습니다. 이전에는 개발자가 이러한 시스템을 지원하기 위해 복잡한 서드 파티 라이브러리나 수동 계산에 의존해야 했습니다.
Temporal API는 여러 캘린더 시스템을 위한 최고 수준의 지원을 제공합니다. Temporal은 캘린더 식별자를 날짜 객체와 연결하여 다양한 문화적 맥락에 필요한 복잡한 연산과 형식을 기본적으로 처리합니다.
구현 방법
Temporal을 사용하여 전역 캘린더 시스템을 지원하려면 다음 안내를 따르세요.
- 캘린더 연결 (필수): 시간 객체 (예:
Temporal.PlainDate)를 만들거나 변환할 때withCalendar()를 사용하여 원하는 캘린더 시스템을 지정해야 캘린더에 민감한 작업을 실행할 수 있습니다. - 안정적인 식별자 사용 (태음태양력에 필수): 태음태양력에서 연도별 특정 월을 식별하려면 숫자
month색인 대신monthCode를 사용해야 합니다. 히브리력 및 중국력과 같이 윤달을 사용하는 캘린더에만 사용하세요. - 캘린더 불변성 준수 (필수): 월 또는 일을 반복할 때 고정된 값 (예: 1년에 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'
});
전략적 구현 및 권장사항
- 권장사항: 월을 반복할 때 12로 가정하는 대신
monthsInYear를 상한으로 사용합니다. - 연도와 관계없이 윤달을 사용하는 달력 (예: 히브리력 또는 중국력)에서 특정 월을 식별하려면
monthCode를 사용합니다. date.month === 12가 연말이라고 가정하지 마세요.date.month === date.monthsInYear를 사용합니다.inLeapYear === true가 1년이 하루 더 길다는 것을 의미한다고 가정하지 마세요. 태음태양력에서는 윤달을 추가할 수 있습니다.- 권장사항: 특정 캘린더 시스템에서 두 날짜를 비교할 때 연도/월/일 속성을 수동으로 비교하는 대신
Temporal.PlainDate.compare()를 사용하세요. - 수동 문자열 연결 대신
toLocaleString()를 사용하여 사용자의 날짜 형식을 지정합니다(권장). - 캘린더별 Temporal 객체를 만들기 전에
Intl.supportedValuesOf('calendar')를 사용하여 환경에서 대상 캘린더 시스템을 지원하는지 확인합니다. - 일부 캘린더 (예: 이슬람력의 변형)는 고정된 계산이 아닌 시각적 관찰에 의존할 수 있다는 점을 유의하세요.
TemporalAPI는 환경의Intl구현을 따르며, 일반적으로 계산된 근사치를 사용합니다. 중요한 문화적 또는 종교적 날짜 계산의 경우 도메인 전문가에게 확인하거나 전문 라이브러리를 사용하세요. toLocaleString()를 사용하여 연호를 사용하는 달력 (예: 일본, 불교)을 사용할 때 연호 이름을 고려합니다.
대체 전략
Temporal의 대체 및 브라우저 지원
아직 네이티브 Temporal API를 지원하지 않는 브라우저의 경우 기능 감지를 사용하고 temporal-polyfill (~15KB 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();
})();