新元号に対応したjdkは今後リリースされるはずだけど、そんな簡単にアップデートできない方(自分含む)に。
前提
- Oracle JDK 8u92
- $JAVA_HOME設定済み
- 諸々文字コードはutf-8
確認用コード
JapaneseEra.java
import java.text.*;
import java.util.*;
public class JapaneseEra {
public static void main(String[] args) throws ParseException {
DateFormat df = new SimpleDateFormat("GGGGy年M月d日", new Locale("ja", "JP", "JP"));
System.out.println(df.format(new Date(System.currentTimeMillis())));
System.out.println(df.parse("平成28年7月14日"));
df.setLenient(false);
System.out.println(df.parse("平成28年7月14日"));
}
}
対応前に実行すると、
$ javac JapaneseEra.java; java JapaneseEra
平成28年7月14日
Thu Jul 14 00:00:00 JST 2016
Thu Jul 14 00:00:00 JST 2016
まあそうですね、と。
新元号に対応する
仮に
- 新元号は「機板」
- 2014/03/15 09:00:00+0900から
その1. 新元号の開始日時をエポックミリ秒にする
1394841600000。
「unix timestamp」なんかでググるか、java.util.Date#getTime()なんかでも変換できるはず。
その2. 新元号をUnicodeに変換する
$ echo "機板" | native2ascii
\u6a5f\u677f
その3. $JAVA_HOME/jre/lib/calendars.properties を編集
calendar.japanese.erasに平成までの定義があるから、そこに新元号を追加。
- nameはその2.のUnicode
- abbrは略称
- sinceはその1.のエポックミリ秒
編集前後のdiffは
name=Meiji,abbr=M,since=-3218832000000; \
name=Taisho,abbr=T,since=-1812153600000; \
name=Showa,abbr=S,since=-1357603200000; \
- name=Heisei,abbr=H,since=600220800000
+ name=Heisei,abbr=H,since=600220800000; \
+ name=\u6a5f\u677f,abbr=K,since=1394841600000
#
# Taiwanese calendar
その4. 確認用コードを再実行する
$ javac JapaneseEra.java; java JapaneseEra
機板3年7月14日
Thu Jul 14 00:00:00 JST 2016
Exception in thread "main" java.text.ParseException: Unparseable date: "平成28年7月14日"
at java.text.DateFormat.parse(DateFormat.java:366)
at JapaneseEra.main(JapaneseEra.java:10)
- 現在のエポックミリ秒は新元号でフォーマットされる
- 平成28年は存在しない(ことになった)から、不正な日付を厳密にチェックするとこける
その他
- Java6でも同じ方法で大丈夫
- Tomcat等起動中のプロセスに反映するのは再起動が必要だった気がする
- 文字化けする場合はnative2asciiの時に-encodingつけるとか
追記
確認用コードでは元号の妥当性を確認するのにDateFormat#setLenient(false)
ってしてるけど、つまり今の元号で書かれた未来の日付は改元後にパースできなくなる可能性がある。
パース対象によって厳密なチェックが必要か、あるいはDateFormat#setLenient(false)
で可能かどうか要件に応じて決める必要がある。