https://blogs.oracle.com/java-platform-group/a-new-japanese-era-for-java
2016年に今上天皇が皇太子さまに譲位する予定であることを発表されました。今上天皇は2019年4月30日(平成31年4月30日)に退位される予定で、2019年4月1日に日本の内閣が、2019年5月1日から始まる新しい元号を発表することになっています。
この新しい元号に備えるための手順をとってきましたが、新元号の発表までこのアップデートの最終化は待つ必要があります。
特にJDKにおいてはいくつかの変更があります。
- グレゴリオ暦の日付を和暦に相当する日付に変換してテキストとして表示する場合、正しい元号名を知っておく必要があります。
- 逆変換、つまり文字列表記の日付を正しい日時に変換する場合には、元号名称を解析し、どの西暦に相当するのかを知っておく必要があります。
- Unicodeは、新しい元号名称を表現する合字を新たに追加します。
java.util.Calendar
クラスに日付を処理するためのメソッドが追加されました。すべての関連APIは、新しい時代を正しく処理するように更新されてきました。JSR 310: Date and Time API新元号に備えて、JDK 12では新元号( “NewEra”)のプレースホルダー名を使用します。JDK 12を使用すると、新元号発表後にリリースされるアップデートで、新元号名がどのように処理されるのかがわかります。
https://jcp.org/en/jsr/detail?id=310
新元号の発表後の次のアップデートリリースは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日
// On versions released after new announcement the 元号 will be replaced with the new era name
java.text.SimpleDateFormat
を使った日付のパースは正しく動作します(訳注:現時点ではDataFormatのFULLスタイルを使わなければ変換できません)。JDK 8以後については、JSR 310 Data and Time APIもアップデートします (このAPIはJDK 7には含まれていません)。
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"
// with 元号 replaced with the new era name
JDK 8以後では、Unicodeコードポイント U+32FF が
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"
));
// => “元号”
// with 元号 replaced with the new era name
java.util.Calendar
クラスに入ります。このコードポイントは新元号の合字用に予約されています。まとめると、以下の通りです。
- 日本の新元号の発表後リリースされるJDKのアップデートで、新元号を正しく取り扱えるようにする
- 新元号発表までは、JDK 12(そしてJDK 11も)は将来の挙動と同様ではあるものの、元号をプレースホルダー名(*)として使用する。
[JDK-8217609] New era placeholder not recognized by java.text.SimpleDateFormat(2019/04/01追記)
https://bugs.openjdk.java.net/browse/JDK-8217609
新元号は令和に決まりました。4月16日のCPU/PSUで反映されていることを確かめましょう…
(2019/04/17追記)
JDK 8u211/212、JDK 11.0.3、JDK 12.0.1のいずれでも、上記コードが正しく動作することを確認しました。プレースホルダーの箇所はもちろん「令和」に置き換わっています。
元記事にコメントしたのですが、なかなか反映されないのでこちらでも。
返信削除"GGGGy 年M ⽉d ⽇"の"月"や"日"が常用漢字でないので "GGGGy年M月d日" で見直したほうがよいかもしれません。
あと、元年の例は誤解をしそうなので、"GGGGy年"は"元号1年"とフォーマットされるなど、訳注を追加したほうがよいかもです。
この辺りのツイートも参考までに。https://twitter.com/yamadamn/status/1109840523404042240
コメントありがとうございます。修正しておきました。
削除