SimpleDateFormatのミリ秒
はじめに
この記事で使用してるのはJava8です。
ミリ秒の結果がおかしい
SimpleDateFormat
でパースしたら、ミリ秒が期待した結果にならなかった。
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS"); Date date = sdf.parse("2018-08-12T12:34:56.12"); System.out.println(date.toInstant()); // -> 2018-08-12T12:34:56.012Z
ミリ秒が.012
で出力されてる。
いやいや。なんで1桁ずれてるのよ。
試しにもう1桁削ってみる。
Date date = sdf.parse("2018-08-12T12:34:56.1"); System.out.println(date.toInstant()); // -> 2018-08-12T12:34:56.001Z
うふふ。2桁ずれた。
逆に増やしてみる。
Date date = sdf.parse("2018-08-12T12:34:56.1234"); System.out.println(date.toInstant()); // -> 2018-08-12T12:34:57.234Z
1秒増えた(^^;
そっか。パターン文字"S"って、Javadocに書いてあるとおり「ミリ秒」なんだ。 「秒の小数部」じゃないのね。 いつも、桁数固定でパースしてたから今まで気付かなかった。
DateTimeFormatterだとどうなるの?
DateTimeFormatterのJavadocでは、パターン文字"S"は「fraction-of-second」って書いてあるから、こっちは期待した結果になりそう。
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS"); LocalDateTime ldt = dtf.parse("2018-08-12T12:34:56.12", LocalDateTime::from); System.out.println(ldt); // -> java.time.format.DateTimeParseException: Text '2018-08-12T12:34:56.12' could not be parsed at index 20
こけたorz
ああ。SimpleDateFormat
と違って桁数厳密なのか。
桁数をあわせて再実行。
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SS"); // Sを1文字削って入力の桁数とあわせた LocalDateTime ldt = dtf.parse("2018-08-12T12:34:56.12", LocalDateTime::from); System.out.println(ldt); // -> 2018-08-12T12:34:56.120
うん。期待した通りの結果。
しかし、私がパースしたい文字列の小数部の長さは可変なので、パターン文字"S"を1文字だけに修正。
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.S"); // Sを1文字だけに修正 LocalDateTime ldt = dtf.parse("2018-08-12T12:34:56.12", LocalDateTime::from); System.out.println(ldt); // -> java.time.format.DateTimeParseException: Text '2018-08-12T12:34:56.12' could not be parsed, unparsed text found at index 21
こけた...。
あれ?たしか可変長パースできたよな...。と次のとおり実行してみる。
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("y-M-d'T'H:m:s.SS"); // S以外のパース文字を1文字に修正 LocalDateTime ldt = dtf.parse("2018-08-12T12:34:56.12", LocalDateTime::from); System.out.println(ldt)); // -> 2018-08-12T12:34:56.120
うん。問題ない。
もう一度、ここからパターン文字"S"を1文字だけに修正して実行。
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("y-M-d'T'H:m:s.S"); // Sも1文字に修正 LocalDateTime ldt = dtf.parse("2018-08-12T12:34:56.12", LocalDateTime::from); System.out.println(ldt); // -> java.time.format.DateTimeParseException: Text '2018-08-12T12:34:56.12' could not be parsed, unparsed text found at index 21
!?
ここでJavadocを再確認して、色々、試してもわけがわからず時間をだいぶ潰す。。。
で、googleさんに聞いてみたらこんな記事が見つかった。
事象はちょっと違うけど、たぶんこれだな。 Java9で修正されてるっぽいのでJava9で実行してみたけど症状変わらず。 Java10ならどうよ?と、Java10をダウンロードして試しても症状変わらず。。。
え?バグじゃないの?もしかして仕様なの?
もう、眠いから明日調べてみよ。。。