Java8 の Date & Time API ではまった。
日経ソフトウェア4月号の「至極の Java クイズ」で JSR310 の問題がでていた。
知らない内容が鍵となっていてとても勉強になった。
しかし、それにもかかわらずはまってしまった。
ここでクイズです。
下記プログラムを実行するとどうなるでしょうか?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
package jp.yucchi.localdateparsetest; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.time.format.ResolverStyle; /** * * @author Yucchi */ public class LocalDateParseTest { public static void main(String[] args) { LocalDate d = LocalDate.parse("2014/3/03", DateTimeFormatter.ofPattern("yyyy/M/d") .withResolverStyle(ResolverStyle.STRICT)); System.out.println(d); } } |
1.2014-03-03
2.2014-3-03
3.2014-3-3
4.実行時エラー
解りましたでしょうか?
このプログラムは DateTimeFormatter でパターンを設定し、ResolverStyle を設定しただけのシンプルなものですね。
LocalDate d = LocalDate.parse(“2014/3/03”, DateTimeFormatter.ofPattern(“yyyy/M/d”)
.withResolverStyle(ResolverStyle.STRICT));
この問題の答えは 4.実行時エラーです。
Exception in thread “main” java.time.format.DateTimeParseException: Text ‘2014/03/10’ could not be parsed: Unable to obtain LocalDate from TemporalAccessor: {YearOfEra=2014, MonthOfYear=3, DayOfMonth=10},ISO of type java.time.format.Parsed
at java.time.format.DateTimeFormatter.createError(DateTimeFormatter.java:1919)
at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1854)
at java.time.LocalDate.parse(LocalDate.java:400)
at jp.yucchi.localdateparsetest.LocalDateParseTest.main(LocalDateParseTest.java:15)
Caused by: java.time.DateTimeException: Unable to obtain LocalDate from TemporalAccessor: {YearOfEra=2014, MonthOfYear=3, DayOfMonth=10},ISO of type java.time.format.Parsed
at java.time.LocalDate.from(LocalDate.java:368)
at java.time.LocalDate$$Lambda$7/980546781.queryFrom(Unknown Source)
at java.time.format.Parsed.query(Parsed.java:226)
at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1850)
… 2 more
ResolverStyle.LENIENT もしくは ResolverStyle.SMART だと 2014-03-03 と表示されます。
何故、ResolverStyle.STRICT だとエラーになるか解りますか?
エラーメッセージを読んでピンッてきたかたもいると思います。
ResolverStyle.STRICT は厳密に判定を下すので DateTimeFormatter.ofPattern(“yyyy/M/d”) の y をきっちり解釈してしまうのです。
ここでパターン設定に使われている y は year-of-era となっています。
これがエラーを引き起こす原因です。
じゃあどうすればいいかというと u を使えばいいのです。
u は year なので厳密に判断される場合でも全然問題ないのです。
よって、このプログラムを正しく動作させるには
LocalDate d = LocalDate.parse(“2014/3/03”, DateTimeFormatter.ofPattern(“uuuu/M/d”)
.withResolverStyle(ResolverStyle.STRICT));
と DateTimeFormatter.ofPattern(“yyyy/M/d”) を DateTimeFormatter.ofPattern(“uuuu/M/d”) としてあげればいいのです。
よく見かけるサンプルは DateTimeFormatter.ofPattern(“yyyy/M/d”) となっているのが多いので注意が必要ですね。(^_^)
TAGS: Java | 2014年3月22日3:18 PM | Comment : 1