先週は和暦を表すJpaneseImperialCalendarクラスを紹介しました。今週は和暦の続きで、和暦の表示、パースについて紹介します。

和暦のフォーマット

日時をフォーマットするために使用されるクラスはjava.text.DateFormatクラスです。

和暦でも西暦でもDateFormatクラスを使用するのは同じなのですが、DateFormatクラスもロケールによってフォーマットが変化します。

さっそく、試してみましょう。

サンプルのソース ImperialCalendarSample3.java

同じ、Dateオブジェクトをロケールの異なる2つのDateFormatオブジェクトを使用して、表示します。

    public ImperialCalendarSample3() {
        Date date = new Date();
 
        // 西暦で表示
        DateFormat gregorianFormat
            = DateFormat.getDateInstance(DateFormat.FULL);
        System.out.println(gregorianFormat.format(date));
 
        // 和暦で表示
        Locale locale = new Locale("ja", "JP", "JP");
        DateFormat japaneseFormat
            = DateFormat.getDateInstance(DateFormat.FULL, locale);
        System.out.println(japaneseFormat.format(date));
    }

これを実行すると次のようになります。

C:\temp>java ImperialCalendarSample3
2007年10月28日
平成19年10月28日

ロケールja_JP_JPだと、年号を用いて表示すること分かりました。

しかし、DateFormatクラスでは決められたパターン(SHORT, MEDIUM, LONG, DEFAULT)でしか表示することができません。自分で表示フォーマットを決めたい場合はjava.text.SimpleDateFormatクラスを使用します。

サンプルのソース ImperialCalendarSample4.java

ここで問題になるのは元号を漢字でフォーマットするにはどうすればいいかということです。

SimpleDateFormatクラスのフォーマット記述子でERAを表すのはGです。では、次のように表示を行なってみましょう。

    public ImperialCalendarSample4() {
        Date date = new Date();
  
        Locale locale = new Locale("ja", "JP", "JP");
        DateFormat format
            = new SimpleDateFormat("Gyyyy年 MM月 dd日", locale);
        System.out.println(format.format(date));
    }

実行したら、次のようになりました。

C:\temp>java ImperialCalendarSample4
H19年 10月 28日

平成と出力して欲しかったのですが、「H」と出力されてしまいました。「H」は平成のHということは分かりますが、意図した結果にならないのは困ったものです。

ここでふと思いついたのは年の表し方です。年はyyとした場合は07年のように2桁でフォーマットされ、yyyyとした場合は2007年のように4桁でフォーマットされます。

これと同じようにGもその個数によってフォーマットが変化するかもしれません。さっそくやってみましょう。

    public ImperialCalendarSample4() {
        Date date = new Date();
  
        Locale locale = new Locale("ja", "JP", "JP");
        DateFormat format1
            = new SimpleDateFormat("Gyyyy年 MM月 dd日", locale);
        System.out.println("G: " + format1.format(date));
  
        DateFormat format2
            = new SimpleDateFormat("GGyyyy年 MM月 dd日", locale);
        System.out.println("GG: " + format2.format(date));
  
        DateFormat format3
            = new SimpleDateFormat("GGGyyyy年 MM月 dd日", locale);
        System.out.println("GGG: " + format3.format(date));
  
        DateFormat format4
            = new SimpleDateFormat("GGGGyyyy年 MM月 dd日", locale);
        System.out.println("GGGG: " + format4.format(date));
    }

ERAを表すGを1個から4個まで変化させて年号を出力しています。

C:\temp>java ImperialCalendarSample4
G: H19年 10月 28日
GG: H19年 10月 28日
GGG: H19年 10月 28日
GGGG: 平成19年 10月 28日

この結果から、Gが4個以上の場合、平成と漢字で元号をフォーマットすることが分かります。

SimpleDateFormatクラスのJavadocにはGがテキストとして扱われ、パターン文字数が4以上の場合フル形式を使用し、それ以外は短い形式または省略された形式があればそれを使用します、と記述されています。元号もこのルールが適用されているわけです。

著者としては、Gが1つの場合はアルファベット、Gが2つの場合は「平」のように漢字1文字、Gが4個以上で「平成」とフォーマットして欲しいのですけどね

この関係は年でも同じです。ロケールがja_JP_JPの場合、yが4つ以上だと1年が元年とフォーマットされます。

サンプルのソース ImperialCalendarSample5.java

先ほどと同じように、yの個数を増やしていきましょう。

    public ImperialCalendarSample5() {
        // JapaneseImperialCalendarオブジェクトを生成
        Locale locale = new Locale("ja", "JP", "JP");
        Calendar calendar = Calendar.getInstance(locale);
        
        // 元年にセット
        calendar.set(Calendar.YEAR, 1);
        Date date = calendar.getTime();
  
        DateFormat format1
            = new SimpleDateFormat("GGGGy年", locale);
        System.out.println("y: " + format1.format(date));
  
        DateFormat format2
            = new SimpleDateFormat("GGGGyy年", locale);
        System.out.println("yy: " + format2.format(date));
  
        DateFormat format3
            = new SimpleDateFormat("GGGGyyy年", locale);
        System.out.println("yyy: " + format3.format(date));
  
        DateFormat format4
            = new SimpleDateFormat("GGGGyyyy年", locale);
        System.out.println("yyyy: " + format4.format(date));
    }

まず、JapaneseImeprialCalendarオブジェクトを取得し、年を元年にセットします。その後、yを変化させて出力を行なっています。

C:\temp>java ImperialCalendarSample5
y: 平成1年
yy: 平成01年
yyy: 平成001年
yyyy: 平成元年

このようにyが4個以上で元年とフォーマットされることが分かります。

しかし、1月1日は元日とはフォーマットしないようです。