【Tips】和暦西暦変換処理と明治時代とJava、C#での実装について(2017/1/10追記)
日付処理にまつわる、明治時代の和暦の考え方について紹介します。
学生時代に習った「明治時代の日付のずれ※」覚えていますか?
※「明治5年12月2日」の翌日が「明治6年1月1日」
なぜ歴史のことをお話しするかというと、アプリケーション、特に業務アプリを作る際に絶対的に必要になってくる「西暦和暦変換処理」について、歴史的背景、Javaでの実装、C#での実装に解説したいと思います。
[歴史的背景]
明治になった9月8日という日付について、和暦年月(太陽太陰暦)の明治1年9月8日であり、西暦では「1868年10月23日」となる。
上記開始日のずれの原因は、明治への改元の詔書が出されたのが1868年10月23日であり、当日付は、慶応4年9月8日、明治1年9月8日と同日を指す。これが翌日改元に基づいた歴史的な明治の開始日となる。
ただし、立年改善に基づいた場合、上記の日付を元に、遡って明治1年1月1日と定められたのが、1868年1月25日となる。
また、明治5年12月2日(1872年12月31日)の翌日から太陽暦(グレゴリオ暦)を採用しており、明治6年(1873年)1月1日としたため、明治5年は12月3日から12月30日までの28日間が存在しない。
<年表>
和暦 | 西暦 (グレゴリウス暦) | 明治時代の 始まり | 歴史 |
---|---|---|---|
慶応3年12月7日 | 1868年1月1日 | 改歴を考慮しない場合の明治1年1月1日 | |
明治1年1月1日 | 1868年1月25日 | 立年改元 | 公式な明治の開始日 |
慶応4年1月1日 | |||
慶応4年9月7日 | 1868年10月22日 | 慶応の終了日 | |
慶応4年9月8日 | 1868年10月23日 | 明治の開始日であるが、慶応の終了日でもある | |
明治1年9月8日 | 翌日改元 | 明治への改元詔書が出された日 歴史的な明治の開始日 |
|
明治5年11月9日 | 1872年12月9日 | 改暦ノ布告 明治5年太政官布告第337号 |
|
明治5年12月2日 | 1872年12月31日 | 明治改暦 和暦における太陽太陰暦の最終日 |
|
明治6年1月1日 | 1873年1月1日 | 和暦でグレゴリウス暦が使われ始めた日 |
<日本史の教科書>
[Javaでの実装]
JavaではJava SE6及びSE8より、標準APIで和暦に対応しています
クラス:JapaneseImperialCalendar(JavaSE6)、JapaneseDate(JavaSE8)
サポート:西暦1873年1月1日/明治6年1月1日
サポート対象外の日付を入れると例外が発生します。
実際に処理をすると「西暦1868年1月1日は例外が発生」します。
てわけで、JavaSE8ベースでテストしてみました。
<テストソース>
<実行結果>
JavaDoc通り、明治6年1月1日より前はサポートしてない模様。
翌日改元に基づいた実装がされていました。
(これって正しいのかな?)
RuntimeException:西暦1868年1月1日 (java.time.DateTimeException: JapaneseDate before Meiji 6 is not supported) RuntimeException:西暦1868年1月1日 (java.time.DateTimeException: JapaneseDate before Meiji 6 is not supported) RuntimeException:西暦1868年1月25日 (java.time.DateTimeException: JapaneseDate before Meiji 6 is not supported) RuntimeException:西暦1868年9月7日 (java.time.DateTimeException: JapaneseDate before Meiji 6 is not supported) RuntimeException:西暦1868年9月8日 (java.time.DateTimeException: JapaneseDate before Meiji 6 is not supported) RuntimeException:西暦1868年9月9日 (java.time.DateTimeException: JapaneseDate before Meiji 6 is not supported) RuntimeException:西暦1868年10月22日 (java.time.DateTimeException: JapaneseDate before Meiji 6 is not supported) RuntimeException:西暦1868年10月23日 (java.time.DateTimeException: JapaneseDate before Meiji 6 is not supported) RuntimeException:西暦1872年12月31日 (java.time.DateTimeException: JapaneseDate before Meiji 6 is not supported) 西暦1873年1月1日 → 明治6年1月1日 西暦1912年1月1日 → 明治45年1月1日 西暦1912年7月29日 → 明治45年7月29日 西暦1912年7月30日 → 大正1年7月30日 西暦1926年1月1日 → 大正15年1月1日 西暦1926年12月24日 → 大正15年12月24日 西暦1926年12月25日 → 昭和1年12月25日 西暦1989年1月1日 → 昭和64年1月1日 西暦1989年1月7日 → 昭和64年1月7日 西暦1989年1月8日 → 平成1年1月8日
[C#での実装]
クラス:JapaneseCalendar
サポート:西暦1868年9月8日
ただし、グレゴリオ暦の西暦1868年9月8日~の変換にしか対応しておらず、これより前の日付を操作しようとした場合、ArgumentOutOfRangeExceptionが発生します。
てわけでこっちもテストしてみました
<テストソース>
<実行結果>
MSDN通り、明治5年まではグレゴリウス暦が反映されていない模様です。
Exception:西暦1868年1月1日 Exception:西暦1868年1月1日 Exception:西暦1868年1月25日 Exception:西暦1868年9月7日 西暦1868年9月8日 → 明治01年9月8日 西暦1868年9月9日 → 明治01年9月9日 西暦1868年10月22日 → 明治01年10月22日 西暦1868年10月23日 → 明治01年10月23日 西暦1872年12月31日 → 明治05年12月31日 西暦1873年1月1日 → 明治06年1月1日 西暦1912年1月1日 → 明治45年1月1日 西暦1912年7月29日 → 明治45年7月29日 西暦1912年7月30日 → 大正01年7月30日 西暦1926年1月1日 → 大正15年1月1日 西暦1926年12月24日 → 大正15年12月24日 西暦1926年12月25日 → 昭和01年12月25日 西暦1989年1月1日 → 昭和64年1月1日 西暦1989年1月7日 → 昭和64年1月7日 西暦1989年1月8日 → 平成01年1月8日
[アプリでの和暦サポートの考え方]
ここまで歴史が複雑で、資料も残っておらず考え方がばらばらの場合、グレゴリウス暦に統一された「1873年1月1日(明治6年1月1日)」から、変換をサポートすることを推奨します。
また、標準APIで実装し、元号が変わった場合、標準APIライブラリが対応するまでの間、和暦のサポートができなくなります。
実態としては、アプリケーションを組む場合は、西暦を採用するか、和暦を採用する場合は個別実装することになるかと思います。
個人的所管だけど、、
日本人だけど、システム屋だから、和暦嫌い!!
-------------------------------------------------------------------------------
2017/1/10追記
本日、元号の改定に関する閣議が発表されました。
こちらの記事とあわせてご覧ください
--------------------------------------------------------------------------------
[歴史系参考]
[JavaSE6参考]
※パッケージプライベートのクラスなためAPIドキュメントが存在しません。
[JavaSE8参考]
JapaneseDate (Java Platform SE 8)
[C#参考]
JapaneseCalendar.MinSupportedDateTime プロパティ - MSDN