다양한 달력 시스템에서 날짜를 어떻게 포맷하나요?
JavaScript의 달력 옵션을 사용하여 전 세계 사용자를 위해 이슬람력, 히브리력, 일본력, 중국력 및 기타 달력 시스템으로 날짜를 표시합니다
소개
대부분의 개발자들은 날짜가 모든 곳에서 동일하게 작동한다고 가정합니다. 2025년 3월 15일에 대한 Date 객체를 생성하고, 형식을 지정한 후 사용자에게 표시합니다. 그러나 사용자가 다른 달력 시스템을 따를 때 이러한 가정은 무너집니다.
많은 문화권에서 그레고리안 달력의 2025년 3월 15일은 완전히 다른 표현 방식을 가집니다. 이슬람 달력을 따르는 사용자에게는 같은 순간이 1447년 라마단 16일에 발생합니다. 히브리 달력 사용자에게는 5785년 아달 II 14일에 해당합니다. 공식적인 맥락에서 일본 사용자에게는 레이와 7년 3월 15일로 표시됩니다.
달력 시스템은 사회가 시간을 계산하는 방식을 결정합니다. 이들은 연도가 언제 시작되는지, 월이 어떻게 구성되는지, 날짜가 어떻게 번호가 매겨지는지를 정의합니다. JavaScript의 Intl.DateTimeFormat API는 17개 이상의 다양한 달력 시스템을 지원하여 각 사용자의 문화적, 종교적 맥락에 따라 날짜를 표시할 수 있게 합니다.
이 강의에서는 달력 시스템이 무엇인지, 왜 존재하는지, 그리고 JavaScript에서 다양한 달력 시스템을 사용하여 날짜 형식을 지정하는 방법을 설명합니다.
달력 시스템이란
달력 시스템은 시간을 조직하고 계산하는 규칙을 정의합니다. 각 시스템은 연도가 언제 시작되는지, 몇 개의 월이 존재하는지, 일수가 어떻게 번호가 매겨지는지, 그리고 연도 번호 매김의 시작점으로 어떤 기원이 사용되는지를 설정합니다.
국제적 맥락에서 널리 사용되는 그레고리안 달력은 예수 그리스도의 추정 탄생일부터 연도를 계산합니다. 이 달력은 28일에서 31일까지 다양한 길이의 12개월을 사용하여 4년마다 윤년이 있는 365일 연도를 만듭니다.
다른 달력 시스템은 다른 구조와 시작점을 사용합니다. 이슬람 달력은 연간 총 354일 또는 355일인 12개의 음력 월을 사용합니다. 히브리 달력은 음력 월과 태양력 연도 정렬을 결합합니다. 일본 달력은 각 천황의 재위와 함께 변경되는 연호를 사용합니다.
이러한 시스템은 다양한 문화권이 종교적 중요성, 천문학적 관찰, 역사적 사건을 기반으로 시간을 추적하는 자체적인 방법을 개발했기 때문에 존재합니다. 많은 문화권에서는 종교적 의식, 공식 문서, 문화 행사를 위해 그레고리안 달력과 함께 전통적인 달력을 계속 사용하고 있습니다.
애플리케이션에서 달력 시스템이 중요한 이유
다양한 문화적 배경을 가진 사용자를 대상으로 하는 애플리케이션은 해당 사용자가 이해하고 기대하는 형식으로 날짜를 표시해야 합니다. 무슬림 사용자를 위한 기도 시간 앱은 이슬람력으로 날짜를 표시해야 합니다. 유대교 종교 의식을 위한 앱은 히브리력 날짜가 필요합니다. 일본 정부 관련 애플리케이션은 일본 연호 형식을 요구합니다.
잘못된 달력 시스템을 사용하면 혼란이 생기고 의도한 대상 사용자에게 애플리케이션을 사용할 수 없게 만들 수 있습니다. 이슬람 휴일 날짜를 그레고리력으로 표시하면 사용자가 수동으로 날짜를 변환해야 합니다. 히브리력 이벤트를 그레고리력 형식으로 보여주면 그 날짜의 종교적 의미가 모호해집니다.
동일한 Date 객체는 달력 시스템에 관계없이 동일한 시간 순간을 나타냅니다. 변경되는 것은 표시를 위해 그 순간을 포맷하는 방식입니다. JavaScript를 사용하면 복잡한 변환 로직 없이 지원되는 모든 달력 시스템에서 모든 날짜를 포맷할 수 있습니다.
calendar 옵션 사용하기
'Intl.DateTimeFormat' 생성자는 날짜 포맷팅 시 사용할 달력 시스템을 지정하는 'calendar' 옵션을 받습니다. 달력 식별자를 문자열 값으로 전달하세요.
const date = new Date('2025-03-15');
const gregorianFormatter = new Intl.DateTimeFormat('en-US', {
calendar: 'gregory',
dateStyle: 'long'
});
const islamicFormatter = new Intl.DateTimeFormat('en-US', {
calendar: 'islamic',
dateStyle: 'long'
});
console.log(gregorianFormatter.format(date));
// 출력: "March 15, 2025"
console.log(islamicFormatter.format(date));
// 출력: "Ramadan 16, 1447 AH"
동일한 Date 객체가 달력 시스템에 따라 다른 포맷된 문자열을 생성합니다. 그레고리력은 2025년 3월 15일을 보여줍니다. 이슬람력은 1447년 라마단 16일(AH)을 보여줍니다.
calendar 옵션은 로케일과 독립적으로 작동합니다. calendar 옵션을 적절한 로케일과 결합하여 영어, 아랍어, 프랑스어 또는 다른 언어로 이슬람 날짜를 포맷할 수 있습니다.
const date = new Date('2025-03-15');
const arabicFormatter = new Intl.DateTimeFormat('ar-SA', {
calendar: 'islamic',
dateStyle: 'long'
});
const englishFormatter = new Intl.DateTimeFormat('en-US', {
calendar: 'islamic',
dateStyle: 'long'
});
console.log(arabicFormatter.format(date));
// 출력: "١٦ رمضان ١٤٤٧ هـ"
console.log(englishFormatter.format(date));
// 출력: "Ramadan 16, 1447 AH"
달력 시스템은 표시할 날짜를 결정하고, 로케일은 언어와 포맷팅 규칙을 결정합니다.
이슬람력으로 날짜 포맷팅하기
이슬람력은 29일 또는 30일로 구성된 12개월을 포함하는 태음력입니다. 완전한 태음년은 약 354일로, 태양력인 그레고리력보다 10~11일 짧습니다. 이로 인해 이슬람 날짜는 시간이 지남에 따라 그레고리력에서 뒤로 이동합니다.
자바스크립트는 여러 이슬람력 변형을 지원합니다. islamic 식별자는 알고리즘 기반 계산을 사용합니다. islamic-umalqura 식별자는 사우디아라비아에서 사용되는 움 알-쿠라 달력을 사용합니다. islamic-civil 식별자는 예측 가능한 표 계산을 사용합니다.
const date = new Date('2025-03-15');
const islamicFormatter = new Intl.DateTimeFormat('en-US', {
calendar: 'islamic',
year: 'numeric',
month: 'long',
day: 'numeric'
});
const umalquraFormatter = new Intl.DateTimeFormat('en-US', {
calendar: 'islamic-umalqura',
year: 'numeric',
month: 'long',
day: 'numeric'
});
console.log(islamicFormatter.format(date));
// 출력: "Ramadan 16, 1447 AH"
console.log(umalquraFormatter.format(date));
// 출력: "Ramadan 16, 1447 AH"
무슬림 사용자를 대상으로 하는 대부분의 애플리케이션에서는 이러한 이슬람력 변형 중 어느 것이든 올바르게 작동합니다. 이들 간의 차이는 작으며 주로 종교적 의식의 정확한 날짜를 결정하는 데 중요합니다.
히브리력으로 날짜 포맷팅하기
히브리력은 유대교 종교 의식에 사용되는 태음태양력입니다. 특정 연도에 윤달을 추가하여 태음월을 태양년과 동기화합니다. 이를 통해 휴일이 계절과 일치하도록 유지합니다.
const date = new Date('2025-03-15');
const hebrewFormatter = new Intl.DateTimeFormat('en-US', {
calendar: 'hebrew',
year: 'numeric',
month: 'long',
day: 'numeric'
});
console.log(hebrewFormatter.format(date));
// 출력: "14 Adar II 5785"
히브리력은 니산, 이야르, 시반, 탐무즈와 같은 히브리 월 이름을 사용합니다. 윤년에는 아다르 I과 아다르 II를 포함합니다. 연도 수는 유대교 전통에 따른 창조 이후의 연도를 나타냅니다.
원어민을 위해 히브리어로 히브리 날짜를 포맷할 수 있습니다.
const date = new Date('2025-03-15');
const hebrewFormatter = new Intl.DateTimeFormat('he-IL', {
calendar: 'hebrew',
year: 'numeric',
month: 'long',
day: 'numeric'
});
console.log(hebrewFormatter.format(date));
// 출력: "י״ד באדר ב׳ ה׳תשפ״ה"
히브리어 출력은 숫자에 히브리 문자를 사용하고 월 이름에 히브리 문자를 사용합니다.
일본 달력으로 날짜 포맷팅하기
일본 달력은 재위 중인 천황을 기준으로 한 연호를 사용합니다. 현재 연호인 레이와(令和)는 2019년 5월 1일 나루히토 천황이 즉위했을 때 시작되었습니다. 연도는 각 연호의 시작부터 숫자로 표시됩니다.
const date = new Date('2025-03-15');
const japaneseFormatter = new Intl.DateTimeFormat('en-US', {
calendar: 'japanese',
year: 'numeric',
month: 'long',
day: 'numeric'
});
console.log(japaneseFormatter.format(date));
// Output: "March 15, 7 Reiwa"
연도는 '7 Reiwa'로 표시되며, 이는 레이와 시대의 7년차를 의미합니다. 이 형식은 일본 공식 문서, 정부 양식 및 공식적인 상황에서 사용됩니다.
일본어로 포맷팅하면 전통적인 일본 날짜 형식이 생성됩니다.
const date = new Date('2025-03-15');
const japaneseFormatter = new Intl.DateTimeFormat('ja-JP', {
calendar: 'japanese',
era: 'long',
year: 'numeric',
month: 'long',
day: 'numeric'
});
console.log(japaneseFormatter.format(date));
// Output: "令和7年3月15日"
출력 결과는 연호(令和), 연도(7年), 월(3月), 일(15日)을 일본 문자로 표시합니다.
중국 달력으로 날짜 포맷팅하기
중국 달력은 음력과 양력을 결합한 태음태양력으로, 중국 설날이나 중추절과 같은 전통적인 중국 명절을 결정하는 데 사용됩니다. 이 달력은 음력 월과 24절기를 결합합니다.
const date = new Date('2025-03-15');
const chineseFormatter = new Intl.DateTimeFormat('en-US', {
calendar: 'chinese',
year: 'numeric',
month: 'long',
day: 'numeric'
});
console.log(chineseFormatter.format(date));
// Output: "Second Month 16, 2025(yi-si)"
중국 달력의 연도에는 숫자 연도와 함께 주기적 이름(이 경우 yi-si)이 포함됩니다. 월 이름은 "First Month"와 "Second Month"와 같은 숫자 지정을 사용합니다.
중국어 포맷팅은 중국 문자를 사용하여 날짜를 표시합니다.
const date = new Date('2025-03-15');
const chineseFormatter = new Intl.DateTimeFormat('zh-CN', {
calendar: 'chinese',
year: 'numeric',
month: 'long',
day: 'numeric'
});
console.log(chineseFormatter.format(date));
// Output: "2025乙巳年二月十六"
페르시아 달력으로 날짜 형식 지정하기
페르시아 달력은 태양력 히즈라력이라고도 불리며, 이란과 아프가니스탄의 공식 달력입니다. 그레고리안 달력과 유사한 구조로 12개월의 태양년을 사용하지만, 월의 길이와 기원이 다릅니다.
const date = new Date('2025-03-15');
const persianFormatter = new Intl.DateTimeFormat('en-US', {
calendar: 'persian',
year: 'numeric',
month: 'long',
day: 'numeric'
});
console.log(persianFormatter.format(date));
// Output: "Esfand 24, 1403 AP"
페르시아력 1403년은 그레고리안력 2025년에 해당합니다. AP는 Anno Persico(페르시아 연호)의 약자입니다.
페르시아어 형식은 페르시아 숫자와 월 이름을 사용합니다.
const date = new Date('2025-03-15');
const persianFormatter = new Intl.DateTimeFormat('fa-IR', {
calendar: 'persian',
year: 'numeric',
month: 'long',
day: 'numeric'
});
console.log(persianFormatter.format(date));
// Output: "۲۴ اسفند ۱۴۰۳ ه.ش."
기타 지원되는 달력 시스템
자바스크립트는 다양한 문화적, 종교적 맥락에 맞는 추가 달력 시스템을 지원합니다.
buddhist 달력은 그레고리안 연도에 543년을 더하며, 태국 및 기타 상좌부 불교 국가에서 사용됩니다.
const date = new Date('2025-03-15');
const buddhistFormatter = new Intl.DateTimeFormat('en-US', {
calendar: 'buddhist',
year: 'numeric',
month: 'long',
day: 'numeric'
});
console.log(buddhistFormatter.format(date));
// Output: "March 15, 2568 BE"
indian 달력은 인도의 공식 시민 달력입니다.
const date = new Date('2025-03-15');
const indianFormatter = new Intl.DateTimeFormat('en-US', {
calendar: 'indian',
year: 'numeric',
month: 'long',
day: 'numeric'
});
console.log(indianFormatter.format(date));
// Output: "Phalguna 24, 1946 Saka"
coptic 달력은 콥트 정교회에서 사용됩니다. ethiopic 달력은 에티오피아에서 사용됩니다.
const date = new Date('2025-03-15');
const copticFormatter = new Intl.DateTimeFormat('en-US', {
calendar: 'coptic',
year: 'numeric',
month: 'long',
day: 'numeric'
});
const ethiopicFormatter = new Intl.DateTimeFormat('en-US', {
calendar: 'ethiopic',
year: 'numeric',
month: 'long',
day: 'numeric'
});
console.log(copticFormatter.format(date));
// Output: "Amshir 6, 1741 ERA1"
console.log(ethiopicFormatter.format(date));
// Output: "Yekatit 6, 2017 ERA1"
지원되는 달력 시스템 찾기
JavaScript 구현에서 지원하는 모든 달력 식별자의 배열을 반환하는 Intl.supportedValuesOf() 메서드를 사용할 수 있습니다.
const calendars = Intl.supportedValuesOf('calendar');
console.log(calendars);
// 출력: ["buddhist", "chinese", "coptic", "dangi", "ethioaa", "ethiopic",
// "gregory", "hebrew", "indian", "islamic", "islamic-civil",
// "islamic-tbla", "islamic-umalqura", "japanese", "persian", "roc"]
정확한 목록은 JavaScript 엔진과 브라우저 버전에 따라 다릅니다. 이 메서드는 항상 달력을 알파벳 순서로 반환합니다.
특정 달력을 사용하기 전에 지원 여부를 확인할 수 있습니다.
const calendars = Intl.supportedValuesOf('calendar');
const supportsIslamic = calendars.includes('islamic');
if (supportsIslamic) {
const formatter = new Intl.DateTimeFormat('en-US', {
calendar: 'islamic',
dateStyle: 'long'
});
console.log(formatter.format(new Date()));
}
이러한 확인을 통해 모든 달력 시스템을 지원하지 않는 환경에서 오류를 방지할 수 있습니다.
유니코드 확장을 사용한 달력 지정
옵션 매개변수를 사용하는 대신 로케일 식별자에 유니코드 확장 키를 사용하여 달력 시스템을 지정할 수 있습니다. 로케일 문자열에 -u-ca- 뒤에 달력 식별자를 추가하세요.
const date = new Date('2025-03-15');
const formatter = new Intl.DateTimeFormat('en-US-u-ca-islamic', {
dateStyle: 'long'
});
console.log(formatter.format(date));
// 출력: "Ramadan 16, 1447 AH"
-u-ca-islamic 확장은 포맷터에게 이슬람력을 사용하도록 지시합니다. 이는 옵션 객체에 calendar: 'islamic'을 전달하는 것과 동일한 결과를 생성합니다.
로케일 문자열과 옵션 객체 모두에서 달력을 지정하면 옵션 객체가 우선합니다.
const date = new Date('2025-03-15');
const formatter = new Intl.DateTimeFormat('en-US-u-ca-islamic', {
calendar: 'hebrew',
dateStyle: 'long'
});
console.log(formatter.format(date));
// 출력: "14 Adar II 5785"
옵션 객체의 히브리력이 로케일 문자열의 이슬람력을 재정의합니다. 달력 시스템을 프로그래밍 방식으로 제어해야 할 때는 옵션 매개변수를 사용하세요. 사용자 환경설정이나 구성에서 로케일 식별자를 사용할 때는 유니코드 확장을 사용하세요.
로케일이 기본 캘린더를 결정하는 방법
캘린더를 지정하지 않으면 포맷터는 로케일의 기본 캘린더를 사용합니다. 대부분의 로케일은 그레고리안 캘린더를 기본값으로 사용하지만, 일부 로케일은 다른 기본값을 사용합니다.
const date = new Date('2025-03-15');
const usFormatter = new Intl.DateTimeFormat('en-US', {
dateStyle: 'long'
});
const saFormatter = new Intl.DateTimeFormat('ar-SA', {
dateStyle: 'long'
});
const ilFormatter = new Intl.DateTimeFormat('he-IL', {
dateStyle: 'long'
});
console.log(usFormatter.format(date));
// 출력: "March 15, 2025"
console.log(saFormatter.format(date));
// 출력: "١٦ رمضان ١٤٤٧ هـ"
console.log(ilFormatter.format(date));
// 출력: "15 במרץ 2025"
미국 영어 로케일은 기본적으로 그레고리안 캘린더를 사용합니다. 사우디아라비아 아랍어 로케일은 기본적으로 이슬람 캘린더를 사용합니다. 이스라엘 히브리어 로케일은 강한 히브리 캘린더 전통이 있음에도 불구하고 기본적으로 그레고리안 캘린더를 사용합니다.
포맷터가 사용하는 캘린더를 확인하려면 resolvedOptions() 메서드를 호출하면 됩니다.
const formatter = new Intl.DateTimeFormat('ar-SA', {
dateStyle: 'long'
});
const options = formatter.resolvedOptions();
console.log(options.calendar);
// 출력: "islamic-umalqura"
해결된 옵션은 ar-SA 로케일이 기본적으로 islamic-umalqura 캘린더 변형을 사용한다는 것을 보여줍니다.
캘린더를 명시적으로 설정해야 하는 경우
사용자의 네이티브 로케일에서 일반적인 표시를 위해 날짜를 포맷팅할 때는 로케일이 캘린더 시스템을 결정하도록 하세요. 사우디아라비아의 사용자들은 이슬람 캘린더 날짜를 기대합니다. 일본 사용자들은 공식적인 맥락에서 일본 연호 포맷팅을 기대합니다. 로케일 기본값은 이러한 기대를 자동으로 처리합니다.
const date = new Date('2025-03-15');
const formatter = new Intl.DateTimeFormat(navigator.language, {
dateStyle: 'long'
});
console.log(formatter.format(date));
// 출력은 사용자의 로케일 및 기본 캘린더에 따라 다름
사용자의 로케일에 관계없이 특정 캘린더 시스템으로 날짜를 표시해야 할 때는 캘린더를 명시적으로 설정하세요. 기도 시간 앱은 항상 이슬람 캘린더 날짜를 표시해야 합니다. 히브리 캘린더 앱은 항상 히브리 날짜를 표시해야 합니다.
const date = new Date('2025-03-15');
const formatter = new Intl.DateTimeFormat(navigator.language, {
calendar: 'islamic',
dateStyle: 'long'
});
console.log(formatter.format(date));
// 출력은 사용자의 언어로 이슬람 캘린더 날짜를 표시
이렇게 하면 캘린더 시스템이 애플리케이션의 목적과 일치하면서도 사용자의 언어 선호도를 존중합니다.
로케일의 기본값과 다른 캘린더 시스템으로 날짜를 표시할 때는 캘린더를 명시적으로 설정하세요. 히브리어 사용자에게 그레고리안 날짜를 표시하거나 영어 사용자에게 이슬람 날짜를 표시하고 싶을 수 있습니다.
const date = new Date('2025-03-15');
const formatter = new Intl.DateTimeFormat('en-US', {
calendar: 'hebrew',
dateStyle: 'long'
});
console.log(formatter.format(date));
// 출력: "14 Adar II 5785"
달력과 다른 옵션 결합하기
calendar 옵션은 모든 다른 Intl.DateTimeFormat 옵션과 함께 작동합니다. dateStyle, timeStyle, weekday와 month 같은 컴포넌트 옵션, 그리고 timeZone과 같은 다른 옵션들과 결합할 수 있습니다.
const date = new Date('2025-03-15T14:30:00');
const formatter = new Intl.DateTimeFormat('en-US', {
calendar: 'islamic',
dateStyle: 'full',
timeStyle: 'long',
timeZone: 'America/New_York'
});
console.log(formatter.format(date));
// 출력: "Saturday, Ramadan 16, 1447 AH at 2:30:00 PM EST"
포맷터는 날짜에 이슬람력을 사용하면서 전체 날짜 스타일, 긴 시간 스타일 및 지정된 시간대를 적용합니다.
또한 개별 컴포넌트 옵션과 함께 calendar 옵션을 사용할 수 있습니다.
const date = new Date('2025-03-15');
const formatter = new Intl.DateTimeFormat('en-US', {
calendar: 'japanese',
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric',
era: 'long'
});
console.log(formatter.format(date));
// 출력: "Saturday, March 15, 7 Reiwa"
era 옵션은 일본력이나 불교력과 같이 연호를 사용하는 달력을 사용할 때 특히 관련이 있습니다.
다양한 달력으로 날짜 범위 포맷팅하기
formatRange() 메서드는 calendar 옵션과 함께 작동하여 모든 달력 시스템에서 날짜 범위를 포맷팅합니다.
const startDate = new Date('2025-03-15');
const endDate = new Date('2025-03-25');
const formatter = new Intl.DateTimeFormat('en-US', {
calendar: 'islamic',
year: 'numeric',
month: 'long',
day: 'numeric'
});
console.log(formatter.formatRange(startDate, endDate));
// 출력: "Ramadan 16 – 26, 1447 AH"
포맷터는 두 날짜 모두에 이슬람력을 적용하고 반복되는 정보를 지능적으로 생략하여 범위로 포맷팅합니다.
성능을 위한 포맷터 재사용
Intl.DateTimeFormat 인스턴스를 생성하는 것은 로케일 데이터와 달력 시스템 정보를 처리하는 작업을 포함합니다. 동일한 달력과 로케일로 여러 날짜를 포맷팅할 때는 포맷터를 한 번 생성하고 재사용하세요.
const formatter = new Intl.DateTimeFormat('en-US', {
calendar: 'islamic',
dateStyle: 'long'
});
const dates = [
new Date('2025-03-15'),
new Date('2025-04-20'),
new Date('2025-06-10')
];
dates.forEach(date => {
console.log(formatter.format(date));
});
// 출력:
// "Ramadan 16, 1447 AH"
// "Dhuʻl-Qiʻdah 22, 1447 AH"
// "Dhuʻl-Hijjah 15, 1447 AH"
이 접근 방식은 날짜 배열을 포맷팅하거나 애플리케이션에서 많은 타임스탬프를 표시할 때 성능을 향상시킵니다.
기억해야 할 사항
달력 시스템은 문화권에 따라 시간을 조직하고 계산하는 방식을 정의합니다. JavaScript는 Intl.DateTimeFormat API를 통해 이슬람력, 히브리력, 일본력, 중국력, 페르시아력, 불교력, 콥트력 등 17개 이상의 다양한 달력 시스템을 지원합니다.
옵션 객체에 calendar 옵션을 지정하거나 로케일 문자열에 유니코드 확장자를 추가하여 달력 시스템을 지정할 수 있습니다. 달력 옵션은 날짜를 포맷하는 달력 시스템을 결정하는 반면, 로케일은 언어와 포맷팅 규칙을 결정합니다.
일반적인 용도로 날짜를 표시할 때는 로케일이 기본 달력을 결정하도록 하세요. 애플리케이션에서 사용자의 로케일 환경설정과 관계없이 특정 달력 시스템이 필요한 경우에는 달력을 명시적으로 설정하세요.
달력 옵션은 스타일, 컴포넌트 옵션, 시간대, 날짜 범위 등 다른 모든 날짜 포맷팅 옵션과 함께 작동합니다. 여러 날짜를 포맷할 때는 성능 향상을 위해 포맷터 인스턴스를 재사용하세요.