히즈리 날짜 (Umm al-Qura / أم القرى)
사우디아라비아의 공식 히즈리 달력은 Umm al-Qura(أم القرى)로, 계산된 달력입니다. 다른 "이슬람" 달력은 다른 규칙을 사용하며 종종 하루 차이가 나므로, 코드와 UI에서 항상 달력 이름을 명시하세요.
규칙
- ISO 그레고리오 날짜(
2026-11-03,DATE컬럼 또는 UTC 타임스탬프)를 저장하세요. 표시용으로만 히즈리로 변환하세요. 사용자가 히즈리 날짜를 입력하면 입력 시 그레고리오로 변환하여 저장하세요. - 표시된 날짜가 어떤 달력을 사용하는지 항상 라벨을 붙이세요: «23 جمادى الأولى 1448هـ» 및 «3 نوفمبر 2026م».
- 히즈리 월은 29일 또는 30일이며, 1년은 354일 또는 355일입니다. 고정된 월 길이를 사용하거나 "다음 달"을 위해 "30일 추가"를 절대 사용하지 마세요.
1448-05-23과 같은 히즈리 문자열은 ISO 8601이 아닙니다. 절대new Date()에 전달하지 마세요; 서기 1448년으로 읽힙니다.- 종교적 날짜(라마단 시작, 이드)는 초승달 관측에 의해 발표되며 인쇄된 Umm al-Qura 날짜와 다를 수 있습니다. 이에 대한 계산된 날짜는 «حسب تقويم أم القرى» 또는 «متوقع»로 표시하고, 확실한 것으로 표시하지 마세요.
JavaScript: Intl을 사용한 형식 지정
const d = new Date(Date.UTC(2026, 10, 3)); // 2026년 11월 3일
new Intl.DateTimeFormat('ar-SA-u-ca-islamic-umalqura', { dateStyle: 'full', timeZone: 'UTC' }).format(d);
// "الثلاثاء، ٢٣ جمادى الأولى ١٤٤٨ هـ"
new Intl.DateTimeFormat('ar-SA-u-ca-islamic-umalqura-nu-latn',
{ day: 'numeric', month: 'long', year: 'numeric', timeZone: 'UTC' }).format(d);
// "23 جمادى الأولى 1448 هـ"
new Intl.DateTimeFormat('en-u-ca-islamic-umalqura-nu-latn',
{ day: 'numeric', month: 'long', year: 'numeric', timeZone: 'UTC' }).format(d);
// "Jumada I 23, 1448 AH"
- 항상
ca-islamic-umalqura를 명시적으로 작성하세요.ar-SA가 히즈리를 의미한다고 의존하지 마세요: 최근 ICU/CLDR(Node 24, 현재 Chrome)에서ar-SA의 기본 달력은 그레고리오입니다. nu-latn(0-9) 또는nu-arab(٠-٩)으로 숫자를 명시적으로 설정하세요. 기본값은 로케일과 버전에 따라 다릅니다:ar-SA는 ٠-٩를, 일반ar는 현재 0-9를 제공합니다.- 정확한 문자열(«هـ» 앞 공백, "AH", "Jumada I" 대 "Jumada al-Ula")은 엔진마다 다릅니다. 포맷된 텍스트를 절대 파싱하지 말고 환경 간 스냅샷 테스트하지 마세요.
formatToParts를 사용하세요. - 시간대가 날짜를 결정합니다.
new Date('2026-11-03')는 UTC 자정이므로timeZone: 'UTC'로 포맷하세요. "사우디아라비아의 오늘"은timeZone: 'Asia/Riyadh'를 사용하세요. 순간2026-11-03T22:30Z는 리야드에서 이미 24 جمادى الأولى입니다.
그레고리오를 히즈리 숫자로 변환
const hijriParts = new Intl.DateTimeFormat('en-u-ca-islamic-umalqura-nu-latn', {
day: 'numeric', month: 'numeric', year: 'numeric', timeZone: 'UTC',
});
export function toHijri(date) {
const p = {};
for (const { type, value } of hijriParts.formatToParts(date)) p[type] = value;
return { year: parseInt(p.year, 10), month: parseInt(p.month, 10), day: parseInt(p.day, 10) };
}
toHijri(new Date(Date.UTC(2026, 10, 3))); // { year: 1448, month: 5, day: 23 }
히즈리를 그레고리오로 변환: 일수 스캔
Intl은 히즈리 날짜를 파싱할 수 없으므로, 그레고리오 날짜를 추정하고 toHijri가 일치할 때까지 근처 일수를 스캔합니다.
const DAY = 86400000;
export function hijriToGregorian(y, m, d) {
// 1 무하람 1 AH는 약 622년 7월 19일(율리우스력 그레고리오)입니다; 평균 월 29.530589일
const est = Date.UTC(622, 6, 19) + Math.round((y - 1) * 354.36667 + (m - 1) * 29.530589 + (d - 1)) * DAY;
for (let off = -20; off <= 20; off++) {
const t = new Date(est + off * DAY);
const h = toHijri(t);
if (h.year === y && h.month === m && h.day === d) return t.toISOString().slice(0, 10);
}
return null; // 해당 날짜 없음 (예: 29일 월의 30일)
}
hijriToGregorian(1447, 9, 1); // "2026-02-18"
hijriToGregorian(1448, 1, 1); // "2026-06-16"
hijriToGregorian(1448, 1, 30); // null (무하람 1448은 29일)
null결과는 사용자 입력을 검증하는 방법입니다; «هذا اليوم غير موجود في هذا الشهر»를 표시하세요.- 월 길이:
hijriToGregorian(y, m, 30) ? 30 : 29. - ICU의 Umm al-Qura 테이블은 1300년부터 1600년 AH까지를 다룹니다. 이 범위를 벗어나면 엔진은 표 형식 달력으로 폴백되므로, 해당 범위의 결과는 Umm al-Qura가 아닙니다.
- 사용자가 입력한 아랍-인도 숫자(٠-٩)를 받아들이려면 파싱 전에 0-9로 변환하세요(
arabic-rtl-web참조).
Python: hijridate
# pip install hijridate (hijri-converter의 후속, 동일한 API)
from hijridate import Hijri, Gregorian
h = Gregorian(2026, 11, 3).to_hijri() # Hijri(1448, 5, 23)
h.isoformat() # '1448-05-23'
h.dmyformat() # '23/05/1448'
h.month_name() # 'Jumada al-Ula'
h.month_name('ar') # 'جمادى الأولى'
h.day_name('ar') # 'الثلاثاء'
h.notation('ar') # 'هـ'
h.month_length() # 30
g = Hijri(1447, 9, 1).to_gregorian() # Gregorian(2026, 2, 18), datetime.date 서브클래스
Hijri.today()
- 구형 코드는
pip install hijri-converter와from hijri_converter import Hijri, Gregorian을 사용합니다. 여전히 작동하지만 이제 DeprecationWarning을 발생시킵니다; import를hijridate로 전환하세요. - 지원 범위: 1 무하람 1343 AH ~ 30 두 알히자 1500 AH (1924-08-01 ~ 2077-11-16 CE). 범위를 벗어나면
OverflowError: date out of range. - 불가능한 날짜는
ValueError를 발생시킵니다. 예:Hijri(1448, 1, 30): "day must be in 1..29 for month". - .NET에서는
HijriCalendar(표 형식 쿠웨이트 알고리즘)가 아닌UmAlQuraCalendar를 사용하세요.
월 이름
1 محرم، 2 صفر، 3 ربيع الأول، 4 ربيع الآخر، 5 جمادى الأولى، 6 جمادى الآخرة، 7 رجب، 8 شعبان، 9 رمضان، 10 شوال، 11 ذو القعدة، 12 ذو الحجة.
철자는 라이브러리마다 다릅니다: ICU는 «ربيع الآخر»를 출력하는 반면 hijridate는 «ربيع الثاني»를 출력합니다; 영어도 다양합니다("Rabiʻ II", "Rabi' al-Thani"). 일관된 UI를 위해 라이브러리 문자열을 혼합하는 대신 월 번호를 자체 목록에 매핑하세요.
함정 (Pitfalls)
- 잘못된 달력. 2026년 11월 3일에 대해 Node 24는
islamic-umalqura로 23을,islamic-civil로 22를,islamic으로 24를 제공합니다. Excel과 Windows "Hijri" 달력은 쿠웨이트 표 형식 알고리즘을 사용합니다. 사우디 날짜에는 Umm al-Qura를 사용하세요. - 시간대로 인한 하루 차이: 날짜가 저장된 동일한 시간대로 포맷하세요.
- 히즈리 날짜 산술. "다음 달"의 경우 월 번호를 증가시키고, 일을 해당 월의 길이로 제한한 다음 변환하세요. 나이와 기간은 그레고리오로 계산하세요.
- 라벨이 없는 날짜. «1/5/1448» 또는 «5/1»과 같은 맨 날짜는 모호합니다; 항상 هـ 또는 م을 추가하세요.
- 혼합 숫자. 페이지당 하나의 숫자 체계를 유지하세요.
알려진 쌍으로 테스트 (Umm al-Qura)
| 히즈리 | 그레고리오 |
|---|---|
| 1 라마단 1447 | 2026-02-18 |
| 1 무하람 1448 | 2026-06-16 |
| 23 주마다 알울라 1448 | 2026-11-03 |
| 10 두 알히자 1446 | 2025-06-06 |