イマカラブログ

イマカラメガネの中の人が、芝居と関係あることないこと好き勝手に書くブログ。

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さんに聞いてみたらこんな記事が見つかった。

qiita.com

事象はちょっと違うけど、たぶんこれだな。 Java9で修正されてるっぽいのでJava9で実行してみたけど症状変わらず。 Java10ならどうよ?と、Java10をダウンロードして試しても症状変わらず。。。

え?バグじゃないの?もしかして仕様なの?

もう、眠いから明日調べてみよ。。。