このエントリは以下のエントリをベースにしています。
This entry is based on the entry written by Aurelio Garicia-Ribeyro (Director of Product Manager in charge of Java SE, Oracle).
https://blogs.oracle.com/java-platform-group/a-new-japanese-era-for-java
2016年に今上天皇(当時)が皇太子さま(当時)に譲位なさる予定と発表されました。今上天皇は2019年4月30日(平成31年4月30日)に退位される予定で、2019年5月1日から始まる新しい元号を令和とすると2019年4月1日に日本の内閣が発表しました。
この新しい元号に備えるための手順をとってきましたが、新元号の発表までこのアップデートの最終化は待つ必要があります。
特にJDKにおいてはいくつかの変更があります。
- グレゴリオ暦の日付を和暦に相当する日付に変換してテキストとして表示する場合、正しい元号名を知っておく必要があります。
- 逆変換、つまり文字列表記の日付を正しい日時に変換する場合には、元号名称を解析し、どの西暦に相当するのかを知っておく必要があります。
- Unicodeは、新しい元号名称を表現する合字を新たに追加します。
JDK 8以降、Java APIには新しいDate and Time API(JSR 310を参照)のほか、古い java.util.Calendar
クラスに日付を処理するためのメソッドが追加されました。すべての関連APIは、新しい時代を正しく処理するように更新されてきました。
JSR 310: Date and Time API
https://jcp.org/en/jsr/detail?id=310
新元号に備えて、JDK 12では新元号( “NewEra”)のプレースホルダー名を使用します。JDK 12を使用すると、新元号発表後にリリースされるアップデートで、新元号名がどのように処理されるのかがわかります。
新元号の発表後の次のアップデートリリースは2019年4月16日(PDT)を予定しています。すべてのサポート対象のJDKである7、8、11 LTS、そして12が新しい元号を扱えるようにアップデートされます。
これらのすべてのバージョンの中で、java.util.Calendar
クラスは正しい値を理解し、返すためにアップデートされます。
import java.util.*;
import java.text.*;
...
new SimpleDateFormat("GGGGy年M月d日",Locale.forLanguageTag("ja-JP-u-ca-japanese")).format(new Calendar.Builder().setDate(2019, Calendar.MAY, 1).build().getTime());
// before the update: 平成31年5月1日,
// after the update: 令和1年5月1日
そして java.text.SimpleDateFormat
を使った日付のパースは正しく動作するようになります(執筆時点ではできず、DateFormatのFULLスタイルを使う必要があります)。
import java.text.*;
...
var sdf = new SimpleDateFormat("GGGGy年M月d日", Locale.forLanguageTag("ja-JP-u-ca-japanese"));
sdf.setLenient(false);
new SimpleDateFormat("Y-M-d", Locale.US).format(sdf.parse("令和2年2月1日"));
// => "2020-2-1"
JDK 8以後については、JSR 310 Data and Time APIもアップデートします (このAPIはJDK 7には含まれていません)。
import java.time.chrono.*;
import java.time.format.*;
import java.time.temporal.*;
...
DateTimeFormatter.ofPattern("GGGGy年M月d日").withChronology(JapaneseChronology.INSTANCE).withLocale(Locale.JAPAN).format(JapaneseDate.of(2020, 2, 1));
// => “令和2年2月1日”
DateTimeFormatter.ofPattern("u-M-d").format(DateTimeFormatter.ofPattern("GGGGy年M月d日").withChronology(JapaneseChronology.INSTANCE).withLocale(Locale.JAPAN).withResolverStyle(ResolverStyle.STRICT).parse("令和2年2月1日"));
// => “2020-2-1”
JapaneseEra.of(3).getDisplayName(TextStyle.FULL,Locale.forLanguageTag("ja-JP-u-ca-japanese"));
// => “令和”
JDK 8以後では、Unicodeコードポイント U+32FF がjava.util.Calendar
クラスに入ります。このコードポイントは新元号の合字用に予約されています。
まとめると、以下の通りです。
- 日本の新元号の発表後リリースされるJDKのアップデートで、新元号を正しく取り扱えるようにする
- 新元号発表までは、JDK 12(そしてJDK 11も)は将来の挙動と同様ではあるものの、元号をプレースホルダー名(*)として使用する。
(*)文字列形式の日付のパースに問題があるため、パースが正しく機能するための4月のアップデートまで待つ必要があります。
[JDK-8217609] New era placeholder not recognized by java.text.SimpleDateFormat
https://bugs.openjdk.java.net/browse/JDK-8217609
(2019/04/17追記)
2019年4月16日のCPU/PSUで無事に反映されていることを確認しましたので、上記のサンプルコードを少々書き換えました。