グレゴリオ暦以外のカレンダーで年号と元号を表示する方法

Intl.DateTimeFormatのcalendarおよびeraオプションを使用して、イスラム暦、ヘブライ暦、中国暦、ペルシア暦、その他の暦システムの年号と元号を表示します

はじめに

グレゴリオ暦は単一の起点から年を数えるため、2024年は単純な数値として表されます。他の暦システムでは年の数え方が異なります。イスラム暦は西暦622年から数えます。ヘブライ暦は伝統的な天地創造の日付から数千年前から数えます。中国暦は連続した数字ではなく、60年周期の干支を使用します。

これらの異なる数え方により、同じ時点でも暦によって異なる年の表現になります。グレゴリオ暦の2024年10月15日は、イスラム暦では1446年、ヘブライ暦では5785年、中国暦では2024年(甲辰、jiǎ-chén)となります。

JavaScriptのIntl.DateTimeFormatは、あらゆる暦システムの年号と元号を表示するオプションを提供します。calendarオプションで使用する暦を選択します。yearおよびeraオプションで年号と元号の表示方法を制御します。数字ではなく干支を使用する暦の場合、formatToParts()メソッドで干支名と対応するグレゴリオ暦の年の両方にアクセスできます。

暦システムによる年号の違い

暦システムは3つの基本的な点で異なります。数え始める起点、年の番号付け方法、元号を使用するかどうかです。

グレゴリオ暦は西暦1年から数え始め、順次増加します。イスラム暦は西暦622年のヒジュラ暦元年(AH)から始まります。ヘブライ暦は紀元前3761年の元年から始まります。各暦には独自の紀元、つまり年の数え始めとなる起点があります。

一部の暦では、永続的に増加する連続した年番号を使用します。グレゴリオ暦、イスラム暦、ヘブライ暦、ペルシア暦がこの方式を採用しています。他の暦では、年名が繰り返されるサイクルを使用します。中国暦では、60年周期の干支年を使用します。60年後、サイクルが繰り返されます。

時代は時間を名前付き期間に分割します。グレゴリオ暦では紀元前と紀元後を使用します。日本の暦では元号を使用します。イスラム暦とヘブライ暦は通常、それぞれの紀元から始まる単一の時代を使用します。中国暦は同じ方法で時代を使用せず、代わりにサイクル内の干支年に依存します。

イスラム暦での年の表示

イスラム暦は、西暦622年のムハンマドのメッカからメディナへの移住(ヒジュラ)から年を数えます。イスラム暦元年はグレゴリオ暦の622年に相当します。イスラム暦は太陰月を使用するため、その年はグレゴリオ暦の年よりも短くなります。これは、イスラム暦の年がより速く進むことを意味し、グレゴリオ暦が2024年のとき、現在イスラム暦は1446年に達しています。

イスラム暦を指定するには、calendarオプションにislamicの値を使用するか、ロケール識別子にUnicode拡張-u-ca-islamicを追加します。

const date = new Date('2024-10-15');

const formatter = new Intl.DateTimeFormat('en-US', {
  calendar: 'islamic',
  year: 'numeric',
  month: 'long',
  day: 'numeric'
});

console.log(formatter.format(date));
// "Rabi' II 12, 1446 AH"

年は1446と表示され、これは2024年10月15日に対応するイスラム暦の年です。英語でイスラム暦の日付を表示すると、時代「AH」(ヒジュラ後)が自動的に表示されます。

異なるロケールでは、それぞれの慣習に従ってイスラム暦の日付をフォーマットします。

const date = new Date('2024-10-15');

const en = new Intl.DateTimeFormat('en-US', {
  calendar: 'islamic',
  year: 'numeric',
  month: 'long',
  day: 'numeric'
});
console.log(en.format(date));
// "Rabi' II 12, 1446 AH"

const ar = new Intl.DateTimeFormat('ar-SA', {
  calendar: 'islamic',
  year: 'numeric',
  month: 'long',
  day: 'numeric'
});
console.log(ar.format(date));
// "١٢ ربيع الآخر ١٤٤٦ هـ"

アラビア語ロケールでは、アラビア・インド数字を使用し、月名をアラビア語で表示します。時代表示は「هـ」(ヒジュラのアラビア語略語)に変わります。

イスラム暦における時代表示の制御

eraオプションは、時代表示の有無と表示方法を制御します。このオプションは3つの値を受け付けます。longは完全な時代名、shortは略称、narrowは最もコンパクトな形式を表します。

const date = new Date('2024-10-15');

const long = new Intl.DateTimeFormat('en-US', {
  calendar: 'islamic',
  year: 'numeric',
  era: 'long'
});
console.log(long.format(date));
// "1446 Anno Hegirae"

const short = new Intl.DateTimeFormat('en-US', {
  calendar: 'islamic',
  year: 'numeric',
  era: 'short'
});
console.log(short.format(date));
// "1446 AH"

const narrow = new Intl.DateTimeFormat('en-US', {
  calendar: 'islamic',
  year: 'numeric',
  era: 'narrow'
});
console.log(narrow.format(date));
// "1446 A"

longの値は「Anno Hegirae」(ラテン語で「ヒジュラ暦の年」を意味する)を生成します。shortの値は「AH」を生成します。narrowの値は「A」のみを生成します。

イスラム暦の変種

イスラム暦には、異なる計算方法を使用する複数の変種があります。JavaScriptは5つの変種をサポートしています。islamicislamic-civilislamic-tblaislamic-umalquraislamic-rgsaです。

islamic-umalqura変種は、天文観測に基づくサウジアラビアの公式暦を使用します。islamic-civil変種は、29日と30日の月を交互に繰り返す固定算術計算を使用します。

const date = new Date('2024-10-15');

const umalqura = new Intl.DateTimeFormat('en-US', {
  calendar: 'islamic-umalqura',
  year: 'numeric',
  month: 'long',
  day: 'numeric'
});
console.log(umalqura.format(date));
// "Rabi' II 12, 1446 AH"

const civil = new Intl.DateTimeFormat('en-US', {
  calendar: 'islamic-civil',
  year: 'numeric',
  month: 'long',
  day: 'numeric'
});
console.log(civil.format(date));
// "Rabi' II 11, 1446 AH"

これらの変種は、月の境界を決定するために異なる計算方法を使用するため、同じグレゴリオ暦の日付に対して異なる日数を生成する可能性があります。

ヘブライ暦での年の表示

ヘブライ暦は、紀元前3761年の伝統的な創造日から年を数えます。このため、ヘブライ暦の年はグレゴリオ暦の年よりもはるかに大きくなります。ヘブライ暦の5785年は、グレゴリオ暦の2024年に相当します。

ヘブライ暦を指定するには、calendarオプションにhebrewの値を使用するか、ロケール識別子にUnicode拡張-u-ca-hebrewを追加します。

const date = new Date('2024-10-15');

const formatter = new Intl.DateTimeFormat('en-US', {
  calendar: 'hebrew',
  year: 'numeric',
  month: 'long',
  day: 'numeric'
});

console.log(formatter.format(date));
// "Tishrei 13, 5785"

年は5785と表示されます。これは2024年10月15日に対応するヘブライ暦の年です。ヘブライ暦は太陰太陽暦であり、月は月の満ち欠けに従いますが、年は周期的な閏月によって太陽年と同期しています。

ヘブライ語ロケールのヘブライ暦の日付は、ヘブライ数字と月名を使用します。

const date = new Date('2024-10-15');

const he = new Intl.DateTimeFormat('he-IL', {
  calendar: 'hebrew',
  year: 'numeric',
  month: 'long',
  day: 'numeric'
});
console.log(he.format(date));
// "י״ג בתשרי ה׳תשפ״ה"

ヘブライ語ロケールでは、数字として使用されるヘブライ文字を含め、日付が完全にヘブライ語で表示されます。

中国暦で年を表示する

中国暦では、連続した年番号の代わりに60年周期の干支を使用します。周期内の各年には、天干と地支の2つの文字で構成される名前があります。2024年は甲辰(jiǎ-chén)で、伝統的な中国占星術では「木の龍」を意味します。

中国暦は干支を使用するため、その表示には連続した年番号を持つ暦とは異なる処理が必要です。

const date = new Date('2024-10-15');

const formatter = new Intl.DateTimeFormat('en-US', {
  calendar: 'chinese',
  year: 'numeric',
  month: 'long',
  day: 'numeric'
});

console.log(formatter.format(date));
// "Ninth Month 13, 2024(jiǎ-chén)"

フォーマットされた出力には、グレゴリオ暦の2024年と括弧内の干支「甲辰」の両方が含まれます。この二重表現により、ユーザーは周期的な干支と対応するグレゴリオ暦の年の両方を理解できます。

中国語ロケールの中国暦の日付は、漢字を使用して表示されます。

const date = new Date('2024-10-15');

const zh = new Intl.DateTimeFormat('zh-CN', {
  calendar: 'chinese',
  year: 'numeric',
  month: 'long',
  day: 'numeric'
});
console.log(zh.format(date));
// "2024甲辰年九月十三"

中国語ロケールでは、干支が漢字で表示されます。このフォーマットは、干支を日付文字列に自然に統合します。

干支と関連する年を抽出する

干支を使用する暦は、周期内の干支と対応するグレゴリオ暦の年という2つの情報を提供します。formatToParts()メソッドは、これらを個別の部分に分離します。

const date = new Date('2024-10-15');

const formatter = new Intl.DateTimeFormat('zh-CN', {
  calendar: 'chinese',
  year: 'numeric',
  month: 'long',
  day: 'numeric'
});

const parts = formatter.formatToParts(date);
console.log(parts);

parts配列には、2つの関連するエントリが含まれます。

[
  { type: 'relatedYear', value: '2024' },
  { type: 'yearName', value: '甲辰' },
  // ... other parts
]

relatedYear部分には、4桁のグレゴリオ暦の年が含まれます。yearName部分には、周期的な干支が含まれます。この分離により、カスタムフォーマットでいずれかまたは両方の値を使用できます。

これらの部分を抽出して、カスタム日付表示を作成できます。

const date = new Date('2024-10-15');

const formatter = new Intl.DateTimeFormat('zh-CN', {
  calendar: 'chinese',
  year: 'numeric',
  month: 'long',
  day: 'numeric'
});

const parts = formatter.formatToParts(date);
const yearName = parts.find(p => p.type === 'yearName')?.value;
const relatedYear = parts.find(p => p.type === 'relatedYear')?.value;

console.log(`Year name: ${yearName}`);
// "Year name: 甲辰"

console.log(`Gregorian year: ${relatedYear}`);
// "Gregorian year: 2024"

この手法は、名前付き年号や周期を使用する任意の暦で機能します。

ペルシア暦で年を表示する

ペルシア暦は太陽ヒジュラ暦とも呼ばれ、イスラム暦と同じ紀元である西暦622年のヒジュラから年を数えます。ただし、ペルシア暦は太陰月ではなく太陽月を使用するため、構造的にはグレゴリオ暦に近いものとなっています。

ペルシア暦を指定するには、calendarオプションにpersianという値を使用するか、ロケール識別子にUnicode拡張-u-ca-persianを追加します。

const date = new Date('2024-10-15');

const formatter = new Intl.DateTimeFormat('en-US', {
  calendar: 'persian',
  year: 'numeric',
  month: 'long',
  day: 'numeric'
});

console.log(formatter.format(date));
// "Mehr 24, 1403 AP"

年は1403と表示されます。これは2024年10月15日に対応するペルシア暦の年です。紀元「AP」(Anno Persico)は英語形式で表示されます。

ペルシア語ロケールのペルシア暦の日付は、ペルシア数字と月名を使用します。

const date = new Date('2024-10-15');

const fa = new Intl.DateTimeFormat('fa-IR', {
  calendar: 'persian',
  year: 'numeric',
  month: 'long',
  day: 'numeric'
});
console.log(fa.format(date));
// "۲۴ مهر ۱۴۰۳ ه‍.ش."

ペルシア語ロケールでは、ペルシア語(ファルシ語)の文字と数字を使用して日付が表示されます。紀元表示「ه‍.ش.」は太陽ヒジュラ紀元のペルシア語略語です。

暦と紀元のオプションを組み合わせる

calendareraのオプションを組み合わせることで、異なる暦システム間で年と紀元の表示方法を正確に制御できます。この組み合わせにより、日付フォーマットを正確に制御できます。

const date = new Date('2024-10-15');

const gregorian = new Intl.DateTimeFormat('en-US', {
  calendar: 'gregory',
  year: 'numeric',
  month: 'long',
  era: 'short'
});
console.log(gregorian.format(date));
// "October 2024 AD"

const islamic = new Intl.DateTimeFormat('en-US', {
  calendar: 'islamic',
  year: 'numeric',
  month: 'long',
  era: 'short'
});
console.log(islamic.format(date));
// "Rabi' II 1446 AH"

const hebrew = new Intl.DateTimeFormat('en-US', {
  calendar: 'hebrew',
  year: 'numeric',
  month: 'long',
  era: 'short'
});
console.log(hebrew.format(date));
// "Tishrei 5785"

グレゴリオ暦とイスラム暦の日付は、eraオプションが設定されているため、紀元表示が表示されます。ヘブライ暦の日付は、ヘブライ暦のフォーマットでは通常省略されるため、この形式では紀元表示が表示されません。

ロケールとカレンダーを組み合わせて、別の文化のカレンダーを使用して1つの言語で日付を表示することもできます。

const date = new Date('2024-10-15');

const englishIslamic = new Intl.DateTimeFormat('en-US', {
  calendar: 'islamic',
  year: 'numeric',
  month: 'long',
  day: 'numeric'
});
console.log(englishIslamic.format(date));
// "Rabi' II 12, 1446 AH"

const arabicIslamic = new Intl.DateTimeFormat('ar-SA', {
  calendar: 'islamic',
  year: 'numeric',
  month: 'long',
  day: 'numeric'
});
console.log(arabicIslamic.format(date));
// "١٢ ربيع الآخر ١٤٤٦ هـ"

両方のフォーマッターはイスラム暦を使用していますが、英語ロケールは英語の月名とラテン数字を生成し、アラビア語ロケールはアラビア語の月名とアラビア・インド数字を生成します。

複数のカレンダーで年を表示する

国際的なユーザーにサービスを提供するアプリケーションでは、同じ日付を複数のカレンダーシステムで表示する必要があることがよくあります。複数のフォーマッターを作成して、並列表現を表示できます。

const date = new Date('2024-10-15');

const calendars = [
  { name: 'Gregorian', calendar: 'gregory' },
  { name: 'Islamic', calendar: 'islamic' },
  { name: 'Hebrew', calendar: 'hebrew' },
  { name: 'Persian', calendar: 'persian' }
];

calendars.forEach(cal => {
  const formatter = new Intl.DateTimeFormat('en-US', {
    calendar: cal.calendar,
    year: 'numeric',
    month: 'long',
    day: 'numeric'
  });
  console.log(`${cal.name}: ${formatter.format(date)}`);
});

これにより次のように出力されます:

Gregorian: October 15, 2024
Islamic: Rabi' II 12, 1446 AH
Hebrew: Tishrei 13, 5785
Persian: Mehr 24, 1403 AP

各カレンダーは、独自の年数カウントシステムと時代表示を使用して、同じ時点を表します。

一般的なユースケース

国際的なアプリケーションでは、ユーザーが期待するカレンダーシステムで日付を表示する必要があります。イスラム銀行アプリケーションは、イスラム暦を使用して取引日を表示します。

const transactionDate = new Date('2024-10-15');

const formatter = new Intl.DateTimeFormat('ar-SA', {
  calendar: 'islamic-umalqura',
  year: 'numeric',
  month: 'long',
  day: 'numeric',
  era: 'short'
});

console.log(`Transaction date: ${formatter.format(transactionDate)}`);
// "Transaction date: ١٢ ربيع الآخر ١٤٤٦ هـ"

宗教カレンダーは、祝日や行事の日付を決定します。ユダヤ暦アプリケーションは、祝日のヘブライ暦の日付を表示します。

const roshHashanah2024 = new Date('2024-10-03');

const formatter = new Intl.DateTimeFormat('he-IL', {
  calendar: 'hebrew',
  year: 'numeric',
  month: 'long',
  day: 'numeric'
});

console.log(`Rosh Hashanah: ${formatter.format(roshHashanah2024)}`);
// "Rosh Hashanah: א׳ בתשרי ה׳תשפ״ה"

歴史アプリケーションは、当時使用されていたカレンダーシステムで日付を表示します。古代ペルシャに関するアプリケーションは、ペルシャ暦を使用して日付を表示します。

const historicalDate = new Date('2024-03-20');

const formatter = new Intl.DateTimeFormat('en-US', {
  calendar: 'persian',
  year: 'numeric',
  month: 'long',
  day: 'numeric',
  era: 'long'
});

console.log(`Persian New Year: ${formatter.format(historicalDate)}`);
// "Persian New Year: Farvardin 1, 1403 Anno Persico"

まとめ

グレゴリオ暦以外のカレンダーは、異なる起点から年をカウントし、異なる番号システムを使用します。イスラム暦は西暦622年からカウントし、現在は1446年頃を表示します。ヘブライ暦は紀元前3761年からカウントし、5785年頃を表示します。中国暦は、連続した数字の代わりに60年周期の干支を使用します。

JavaScriptのIntl.DateTimeFormatは、calendarオプションを通じてこれらのカレンダーシステムをサポートしています。値にはislamichebrewchinesepersianなどが含まれます。yearオプションは年を表示するかどうかを制御し、eraオプションは時代表示を表示するかどうか、およびその表示方法を制御します。

名前付き年号を使用する暦は、formatToParts()を通じて2つの情報を提供します。yearName部分には周期的な年号名が含まれます。relatedYear部分には対応するグレゴリオ暦の年が含まれます。これにより、アプリケーションはいずれか一方または両方の値を表示できます。

異なるロケールでは、同じ暦が異なる方法でフォーマットされます。イスラム暦は英語ではラテン数字で表示され、アラビア語ではアラビア・インド数字で表示されます。フォーマットは暦の年号体系を維持しながら、ロケールの慣習に自動的に適応します。