Java で和暦

仕事の関係でちょっと調べてみた。
自分では必要がない限りほとんど使いませんが。(^^;)

Java6

すでに色々なサイトで取り上げられていますが、Java6 から標準で和暦が扱えます。
java.util.JapaneseImperialCalendar というクラスで実現されていますが、クラスが package private なので、直接使うことはできず、以下のように Locale を指定して利用します。

Locale locale = new Locale("ja", "JP", "JP");
Calendar jCal = Calendar.getInstance(locale);
jCal.clear();
// H07.01.23 01:23:45
jCal.set(Calendar.ERA, 4);
jCal.set(7, 0, 23, 1, 23, 45);

元号について、HEISEI のような定数も JapaneseImperialCalendar に定義されているのですが、package private なので使うことができません。(^^;)


西暦 (グレゴリオ暦) との変換はこんな感じ。

Calendar gCal = Calendar.getInstance();
gCal.setTimeInMillis(jCal.getTimeInMillis());
// 西暦1995年
assertEquals(1995, gCal.get(Calendar.YEAR));

GregorionCalendar は public なので、直接 new することもできます。

Calendar gCal = new GregorianCalendar();
gCal.setTimeInMillis(jCal.getTimeInMillis());
// 西暦1995年
assertEquals(1995, gCal.get(Calendar.YEAR));

西暦から和暦への変換もできます。

// 1995-01-23 01:23:45
Calendar gCal = new GregorianCalendar(1995, 0, 23, 1, 23, 45);
Locale locale = new Locale("ja", "JP", "JP");
Calendar jCal = Calendar.getInstance(locale);
jCal.setTimeInMillis(gCal.getTimeInMillis());
// 平成7年
assertEquals(4, jCal.get(Calendar.ERA));
assertEquals(7, jCal.get(Calendar.YEAR));


DateFormat で和暦を出力する方法です。
Calendar は西暦でも和暦でもかまいません。

// 1995-01-23
Calendar gCal = new GregorianCalendar(1995, 0, 23);
Locale locale = new Locale("ja", "JP", "JP");
DateFormat df = DateFormat.getDateInstance(DateFormat.DEFAULT, locale);
df.setTimeZone(gCal.getTimeZone());
System.out.println(df.format(gCal.getTime())); // "H7.01.23"

フォーマットを指定する場合は G を使用します。

// 1995-01-23
Calendar gCal = new GregorianCalendar(1995, 0, 23);
Locale locale = new Locale("ja", "JP", "JP");
DateFormat df = new SimpleDateFormat("Gyy.MM.dd", locale);
df.setTimeZone(gCal.getTimeZone());
System.out.println(df.format(gCal.getTime())); // "H07.01.23"

GGGG のように4文字以上指定すると、"平成07" と漢字で出力されます。

ICU (International Components for Unicode)

IBM が公開しているライブラリで、和暦は com.ibm.icu.util.JapaneseCalendar というクラスで扱うことができます。
JapaneseCalendar は public なので、直接 new することができます。

// H07.01.23 01:23:45
jCal = new JapaneseCalendar(7, 0, 23, 1, 23, 45);
jCal.set(Calendar.ERA, JapaneseCalendar.HEISEI);

明治から平成までの元号は JapaneseCalendar に定義されている定数を使うことができます。
コンストラクタの引数で一緒に指定できても良いと思うのですが...

JapaneseCalendar の Javadoc を読むと、

JapaneseCalendar usually should be instantiated using Calendar.getInstance(ULocale) passing in a ULocale with the tag "@calendar=japanese".

という記述があります。
おそらくこういうことかなと思います。

ULocale locale = new ULocale("ja", "JP")
    .setKeywordValue("calendar", "japanese");
Calendar jCal = Calendar.getInstance(locale);

西暦/和暦の変換方法は Java6 とほとんど同じです。


DateFormat の使用方法も Java6 と同様です。
Calendar は西暦でも和暦でもかまいません。

// 1995-01-23
Calendar gCal = new GregorianCalendar(1995, 0, 23);
ULocale locale = new ULocale("ja", "JP")
    .setKeywordValue("calendar", "japanese");
DateFormat df = DateFormat.getDateInstance(DateFormat.DEFAULT, locale);
df.setTimeZone(gCal.getTimeZone());
System.out.println(df.format(gCal.getTime())); // "平成07/01/23"

フォーマットを指定する場合は G を使用します。

// 1995-01-23
Calendar gCal = new GregorianCalendar(1995, 0, 23);
ULocale locale = new ULocale("ja", "JP")
    .setKeywordValue("calendar", "japanese");
DateFormat df = new SimpleDateFormat("Gyy.MM.dd", locale);
df.setTimeZone(gCal.getTimeZone());
System.out.println(df.format(gCal.getTime())); // "平成07.01.23"

ドキュメントの記述を見つけられませんでしたが、GGGGG のように5文字以上指定すると、"H07" とアルファベットで出力されるようです。

和暦豆知識

  • 明治までは天皇の即位と関係なく改元されることがあったのは有名なこと。
  • 明治までは改元されると年始まで遡って適用される (即年改元)。
  • 1873-01-01 から現在の暦 (グレゴリオ暦) が採用された。
  • 大正、昭和は天皇が亡くなられたその日に改元され、その日の最初に遡って適用される (即日改元) 。
    • 1912-07-30 は明治45年でもあり、大正元年でもある。
    • 1926-12-25 は大正15年でもあり、昭和元年でもある。
  • 平成以降は天皇が亡くなられた次の日に改元される (踰日改元)。
    • 1989-01-07 までは昭和64年。
    • 1989-01-08 から平成元年。

元ネタはこちら。

Java6 と ICU の違い

  • 1873-01-01 以前は旧暦のはずだが、どちらも考慮されていない。
  • Java6 では、明治以降の元号しか扱えない (MEIJI=1,... HEISEI=4)。
  • ICU では、明治以前の元号も扱える (MEIJI=232,... HEISEI=235)。
    • ただし、旧暦に対応していないので、はたして意味があるのか...?
  • Java6 では、1868/01/01 以降を明治元年として扱う。
  • ICU では、1868/09/08 以降を明治元年として扱う。
    • 1868/09/07 までは慶応4年。
  • Java6、ICU とも 1912-07-30 以降は大正元年として扱う。
    • 1912-07-29 までが明治45年。
  • Java6、ICU とも 1926-12-25 以降は昭和元年として扱う。
    • 1926-12-24 までが大正15年。
  • Java6、ICU とも 1989-01-08 以降を平成元年として扱う。
    • 1989-01-07 までは昭和64年。
  • Java6 では、DateFormat の標準が "H7.01.23" のような形式。
    • 元号はアルファベット。
    • 年が1桁の場合、0埋めなし。
    • 年月日の区切りは「.(ピリオド)」。
  • ICU では、DateFormat の標準が "平成07/01/23" のような形式。
    • 元号は漢字。
    • 年が1桁の場合、0埋めあり。
    • 年月日の区切りは「/(スラッシュ)」。