西暦と和暦を併記したループ文【1990(平成2年)のような表記を作る】

SelectBoxで「西暦 (平成○○年）」のような、西暦と和暦を両方表示するような仕様の実装を行うことになった。

Javaで和暦→西暦、西暦→和暦に変換する
https://qiita.com/u-chida/items/31b3415a52f0e1818ab2

和暦はこれで取れる

引用すると

```
//ロケールを指定してCalendarインスタンスを取得
Locale locale = new Locale("ja", "JP", "JP");
Calendar calendar = Calendar.getInstance(locale);

//calendar.getTime()で現在日時を取得して和暦にフォーマットする
DateFormat japaseseFormat = new SimpleDateFormat("GGGGy年M月d日", locale);
String dateStr = japaseseFormat.format(calendar.getTime());
System.out.println("和暦:" + dateStr);

//和暦にフォーマットした現在日時を西暦にパースする
//日付の妥当性をチェックするためsetLenient()にfalseを渡す
calendar.setLenient(false);
Date date = japaseseFormat.parse(dateStr);
System.out.println("西暦:" + date);   
```

で、1990年から2000年までの和暦と併記することにした。

```
for (int seireki = 1990 ; seireki <= 2000; seireki++ ){

	// ロケールを指定してCalendarインスタンスを取得
	Locale locale = new Locale("ja", "JP", "JP");
	Calendar calendar = Calendar.getInstance(locale);
	// 値のクリア
	calendar.clear();
	// 年を設定
	calendar.set(Calendar.YEAR, seireki);

	// calendar.getTime()で現在日時を取得して和暦にフォーマットする
	DateFormat japaseseFormat = new SimpleDateFormat("(GGGGy年)", locale);
	String dateStr = japaseseFormat.format(calendar.getTime());

	System.out.println(seireki + dateStr);
}
```

結果

```
1990(平成1990年)
1991(平成1991年)
1992(平成1992年)
1993(平成1993年)
1994(平成1994年)
1995(平成1995年)
1996(平成1996年)
1997(平成1997年)
1998(平成1998年)
1999(平成1999年)
2000(平成2000年)
```

イケてない。
`calendar.getTimeInMillis()`で中身を見てみたら「633798000000」とか悲惨な値が入っていた。

calendarのロケールが和暦なので、yearに1990を入れたら平成1990年になる。
当たり前の話なのだ。

しかし、残念なことにロケールと年を同時に指定したコンストラクタはJava6にはない。

改善案

```
for (int seireki = 1990 ; seireki <= 2000; seireki++ ){

	// ロケールを指定してCalendarインスタンスを取得
	Locale locale = new Locale("ja", "JP", "JP");
	// 1990年のカレンダーを作る
	Calendar greCal = new GregorianCalendar(seireki, 1, 1);
	Calendar calendar = Calendar.getInstance(locale);
	// 値のクリア
	calendar.clear();
	// カレンダーから年を設定
	calendar.setTimeInMillis(greCal.getTimeInMillis());

	// calendar.getTime()で現在日時を取得して和暦にフォーマットする
	DateFormat japaseseFormat = new SimpleDateFormat("(GGGGy年)", locale);
	String dateStr = japaseseFormat.format(calendar.getTime());

	System.out.println(seireki + dateStr);
}
```

```
1990(平成2年)
1991(平成3年)
1992(平成4年)
1993(平成5年)
1994(平成6年)
1995(平成7年)
1996(平成8年)
1997(平成9年)
1998(平成10年)
1999(平成11年)
2000(平成12年)
```
いい感じ。
平成と昭和の境目もバッチリ（1989年生まれは一律平成1年扱い）

```
1987(昭和62年)
1988(昭和63年)
1989(平成1年)
1990(平成2年)
```

本当は1年は元年にすべきなのだろうか…。
とりあえず上手くできたけれど、本当にこれでいいのかは悩む。


2017/11/17 追記
上記はJava6でやっていたのですが、Java8で修正。
コメントを受けて「1989年は昭和と平成」で表示に変更。

```
import java.time.chrono.JapaneseDate;
import java.time.format.DateTimeFormatter;

public class Qiita21ee9377032b650c2de6 {
	public static void main(String[] args) {
		QiitaExecute qiitaExe = new QiitaExecute();
		qiitaExe.execute();
	}

}
class QiitaExecute {
	
	private final DateTimeFormatter japaseseFormat = DateTimeFormatter.ofPattern("GGGGy年");

	/**
	 * 実行
	 */
	public void execute() {
		for (int annoDomini = 1987; annoDomini <= 1990; annoDomini++) {
			String eraString = getEraString(annoDomini);
			System.out.println(annoDomini + "(" + eraString + ")");
		}
	}

	/**
	 * 和暦返却
	 * 西暦を渡し、元旦から年末の間に元号の変更がある場合は両方の元号を「・」で連結して返す
	 * 元号の変更がない場合は元旦の元号を返す
	 * @param annoDomini
	 * @return
	 */
	private String getEraString(int annoDomini) {

		// 元旦
		// （JapaneseDateの月は1～12で表示）
		JapaneseDate japaneseNewYearDate = JapaneseDate.of(annoDomini, 1, 1);
		// 年末
		JapaneseDate japaneseNewYearEveDate = JapaneseDate.of(annoDomini, 12, 31);

		// 元号が同じ場合は元旦の元号を返し、それ以外は元旦と年末を「・」で連結して返す
		if (japaneseNewYearDate.getEra().getValue() == japaneseNewYearEveDate.getEra().getValue()) {
			return japaseseFormat.format(japaneseNewYearDate);
		} else {
			return japaseseFormat.format(japaneseNewYearDate) + "・" + japaseseFormat.format(japaneseNewYearEveDate);
		}
	}
}
```

結果

```
1987(昭和62年)
1988(昭和63年)
1989(昭和64年・平成1年)
1990(平成2年)
```

1989(昭和64年・平成元年)の表示にするかは悩みどころ。日本人なので元年にしたい気持ちがある。

```
1987(昭和62年)
1988(昭和63年)
1989(昭和64年)
1989(平成1年)
1990(平成2年)
```
が正しい表示なのかもしれないが、1989年、1990年生まれが戸惑う可能性がある。
（1990年生まれは1989の下にあるものと思うから。セレクトボックスをキーボードで選んでる人とかミスる可能性を考慮）