JavaScriptで日付データを扱う際、日本のシステム開発において避けて通れないのが和暦への変換処理です。
近年のモダンなJavaScript環境では、標準機能のみで高度な和暦変換が可能になっています。
かつては複雑な分岐ロジックを自作する必要がありましたが、現在は国際化APIであるIntl.DateTimeFormatを利用するのが主流です。
この記事では、標準機能を用いた変換方法から、実務で役立つ「元年」表記への対応、さらには外部ライブラリを用いた実装までを詳しく解説します。
標準機能「Intl.DateTimeFormat」による和暦変換
モダンブラウザやNode.js環境であれば、JavaScriptの標準APIであるIntl.DateTimeFormatを使用するのが最も効率的です。
このAPIは、OSやブラウザが持つロケール情報を利用して、言語や地域に応じた適切なフォーマットを出力します。
基本的な変換コード
和暦を取得するためには、コンストラクタの第2引数にオプションを指定します。
具体的には、calendarプロパティに"japanese"を指定することがポイントです。
// 和暦変換の基本実装
const date = new Date(2026, 4, 1); // 2026年5月1日
const formatter = new Intl.DateTimeFormat('ja-JP-u-ca-japanese', {
era: 'long',
year: 'numeric',
month: 'long',
day: 'numeric'
});
console.log(formatter.format(date));
令和8年5月1日
上記のコードでは、ロケール識別子としてja-JP-u-ca-japaneseを指定しています。
これにより、日本のロケールかつ和暦カレンダーを使用することを明示的に宣言しています。
オプションの「era」を「long」に設定することで、「令和」や「平成」といった元号が正しく表示されます。
「1年」を「元年」と表示するカスタマイズ
Intl.DateTimeFormatの標準出力では、元号の1年目が「1年」と表記されます。
しかし、日本の慣習では「元年」と表記することが一般的です。
これを実現するには、文字列置換処理を組み合わせる必要があります。
/**
* 和暦に変換し、1年を元年に書き換える関数
* @param {Date} date - 変換対象の日付
* @returns {string} 和暦表記の文字列
*/
function formatToWareki(date) {
const formatter = new Intl.DateTimeFormat('ja-JP-u-ca-japanese', {
era: 'long',
year: 'numeric',
month: 'long',
day: 'numeric'
});
let result = formatter.format(date);
// 「1年」を「元年」に置換(正規表現で安全に処理)
return result.replace(/1年/, '元年');
}
console.log(formatToWareki(new Date(2019, 4, 1))); // 令和元年5月1日
console.log(formatToWareki(new Date(1989, 0, 8))); // 平成元年1月8日
令和元年5月1日
平成元年1月8日
このように、単純な正規表現を用いることで、日本のビジネスルールに即した表記を簡単に実装できます。
各元号の期間と自作ロジックでの実装
ライブラリを使わず、かつ標準APIの挙動を詳細に制御したい場合は、自作の変換ロジックを構築します。
これには、各元号が開始された日付を正確に把握しておく必要があります。
主要な和暦の開始日一覧
JavaScriptで判定を行うために必要な、明治以降の元号データは以下の通りです。
| 元号 | 開始年月日(西暦) | 読み |
|---|---|---|
| 明治 | 1868年1月25日 | Meiji |
| 大正 | 1912年7月30日 | Taisho |
| 昭和 | 1926年12月25日 | Showa |
| 平成 | 1989年1月8日 | Heisei |
| 令和 | 2019年5月1日 | Reiwa |
なお、明治の開始日については諸説ありますが、グレゴリオ暦換算では1868年1月25日が一般的です。
自作変換関数の実装例
日付オブジェクトを引数に取り、各元号の閾値と比較して和暦を算出するロジックを記述します。
const ERAS = [
{ name: '令和', start: new Date(2019, 4, 1) },
{ name: '平成', start: new Date(1989, 0, 8) },
{ name: '昭和', start: new Date(1926, 11, 25) },
{ name: '大正', start: new Date(1912, 6, 30) },
{ name: '明治', start: new Date(1868, 0, 25) }
];
function getJapaneseEra(date) {
// 該当する元号を検索
const era = ERAS.find(e => date >= e.start);
if (!era) return "対応外の期間です";
// 和暦の年を計算
const year = date.getFullYear() - era.start.getFullYear() + 1;
const yearStr = year === 1 ? '元' : year;
return `${era.name}${yearStr}年${date.getMonth() + 1}月${date.getDate()}日`;
}
console.log(getJapaneseEra(new Date(1995, 0, 17)));
平成7年1月17日
自作ロジックのメリットは、「どの時点をもって改元とするか」をコード内で厳密に定義できる点にあります。
また、古いブラウザ環境など、国際化APIが不完全な環境でも安定して動作します。
外部ライブラリを活用した和暦変換
プロジェクトで既に日付操作ライブラリを導入している場合、そのエコシステムを利用するのも賢い選択です。
特に「Day.js」は軽量であり、日本国内でも多くの採用実績があります。
Day.jsによる実装
Day.js本体には和暦機能はありませんが、標準のロケール設定で和暦の表示をサポートしています。
ただし、Day.jsで和暦を扱う場合でも、内部的にはIntl.DateTimeFormatを利用することが多いです。
// Day.jsを使用する場合の例(CDNやnpmで導入済みと仮定)
// 通常、Day.jsで和暦を扱うにはIntlオブジェクトをラップするプラグイン等を利用します。
const now = dayjs('2026-05-20');
// 標準的なフォーマット
console.log(now.format('YYYY/MM/DD'));
ライブラリを使用する最大の利点は、日付の計算(1ヶ月後、10日前など)を行った直後に、そのままフォーマットを適用できる柔軟性にあります。
入力フォームでの和暦変換の実装ポイント
ユーザーが入力した和暦を西暦に変換してサーバーへ送信する、といった逆変換のニーズも頻繁に発生します。
これには、セレクトボックスで元号を選択させ、数値入力を西暦に合算する手法が最も確実です。
和暦から西暦への計算式
和暦の年数に、それぞれの元号の開始前年(オフセット値)を加算することで西暦を求められます。
- 令和:和暦年 + 2018 = 西暦
- 平成:和暦年 + 1988 = 西暦
- 昭和:和暦年 + 1925 = 西暦
- 大正:和暦年 + 1911 = 西暦
例えば、「令和8年」は 8 + 2018 = 2026 と計算できます。
このように、プログラム内部では西暦で管理し、表示層でのみ和暦に変換するのがシステム設計の定石です。
注意点とエッジケースの対策
和暦変換を実装する際には、いくつか注意すべき特殊なケースが存在します。
改元日の取り扱い
1989年1月7日は「昭和64年」ですが、翌日の1月8日は「平成元年」です。
自作ロジックを作成する場合、Dateオブジェクトの時間部分まで考慮しないと、改元日がズレるリスクがあります。
Intl.DateTimeFormatを使用すれば、これらの境界値は自動的に正しく処理されます。
ブラウザによる動作の差異
稀に古いブラウザや特定の実行環境では、Intlオブジェクトがサポートされていない、あるいは和暦カレンダーデータが欠落している場合があります。
実務では、実行環境がIntl.DateTimeFormatをサポートしているかを確認する「ポリフィル」やチェック処理を入れることが推奨されます。
if (typeof Intl !== 'undefined' && Intl.DateTimeFormat) {
// Intlが使える場合の処理
} else {
// 代替ロジック、あるいはエラー処理
}
「モダンブラウザ対応」が前提であれば過度な心配は不要ですが、基幹システムなどの開発では念頭に置いておくべきです。
まとめ
JavaScriptにおける和暦変換は、現在ではIntl.DateTimeFormatを活用することで非常にシンプルに実装可能です。
特定の表記ルール(元年表記など)が必要な場合のみ、正規表現などを用いた補助的な関数を作成するのがベストな構成と言えます。
一方で、特定の元号の境界線を厳密に制御したい場合や、古い環境への互換性を保つ必要がある場合には、各元号の開始日を定義した自作ロジックが有効です。
システム要件に合わせて、標準APIの利便性と自作ロジックの確実性を使い分けるようにしましょう。
今回紹介したコード例を参考に、ユーザーにとって親しみやすい日本のカレンダー表記をぜひ実装してみてください。
