CSVで渡されてくるデータの中に、日時データにミリ秒以下のものが付いているものがあり、そのパースをするとなんか読み込んだ時刻が微妙にずれてしまう、という問題が起こりました。
日付が「2015-05-08 00:00:00.123456789」のような形式でわたされるため、
String dateStr = "2015-05-08 00:00:00.123456789"; SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSSSSS"); Date date = dateFormat.parse(dateStr);
のようにしてパースさせたのですが、9時間ズレるとかではなく中途半端に時間がずれてしまうのです。
なんでこうなるんだろう?と思ってちょっとテストコードを書いてみました。
out.println(testCalendar("2015-05-08 00:00:00", "yyyy-MM-dd HH:mm:ss")); out.println(testCalendar("2015-05-08 00:00:00.123", "yyyy-MM-dd HH:mm:ss.SSS")); out.println(testCalendar("2015-05-08 00:00:00.1234", "yyyy-MM-dd HH:mm:ss.SSSS")); out.println(testCalendar("2015-05-08 00:00:00.12345", "yyyy-MM-dd HH:mm:ss.SSSSS")); out.println(testCalendar("2015-05-08 00:00:00.123456", "yyyy-MM-dd HH:mm:ss.SSSSSS")); out.println(testCalendar("2015-05-08 00:00:00.1234567", "yyyy-MM-dd HH:mm:ss.SSSSSSS")); out.println(testCalendar("2015-05-08 00:00:00.12345678", "yyyy-MM-dd HH:mm:ss.SSSSSSSS")); out.println(testCalendar("2015-05-08 00:00:00.123456789","yyyy-MM-dd HH:mm:ss.SSSSSSSSS")); public String testCalendar(String dateStr, String formatStr) throws ParseException { String out = ""; SimpleDateFormat dateFormat = new SimpleDateFormat(formatStr); Date date = dateFormat.parse(dateStr); Calendar cal = Calendar.getInstance(); cal.setTime(date); date = cal.getTime(); out += "parsed date: " + dateFormat.format(date); return out; }
結果
parsed date: 2015-05-08 00:00:00 parsed date: 2015-05-08 00:00:00.123 parsed date: 2015-05-08 00:00:01.0234 parsed date: 2015-05-08 00:00:12.00345 parsed date: 2015-05-08 00:02:03.000456 parsed date: 2015-05-08 00:20:34.0000567 parsed date: 2015-05-08 03:25:45.00000678 parsed date: 2015-05-09 10:17:36.000000789
ということで、3桁までならば正常にパースされているようです。
ぐぐってみると、下記ページを見てなるほど、となりました。
[Seasar-user:8699] Re: Timestamp型の秒以下の桁を取得するには
TimestampConverter は SimpleDateFormat を使っており,
SimpleDateFormat のパターン文字 S は「ミリ秒」なので
4 桁以上指定しても意味はありません.
ミリ秒だから本来なら3桁までのはずなので、それよりでかい桁については律儀にミリ秒を秒や分、日付に計算しなおしてくれてたのですね。
ここで渡されてくる9桁の「ミリ秒」はそういう意図のデータではないし、まあミリ秒以下のデータは不要であったため、前処理でカットしてパースするようにしました。
自分のように、DBから渡されたデータを、そのまま多桁の「S」を使ったフォーマットで読み込むと、この問題にあたりますので気をつけて。