Why incorrect convert from string to date?

2019-08-18 00:51发布

问题:

In my Kotlin code:

   const val TS_DATE_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS"
   val ts = responseJsonObject.get("TS").getAsString()
   val tsDate = SimpleDateFormat(TS_DATE_PATTERN).parse(ts)
   val tsDateAsString = SimpleDateFormat(TS_DATE_PATTERN).format(tsDate)
   logger.info("ts = " + ts + " -> tsDate = " + tsDate + " -> tsDateAsString = " + tsDateAsString)

And here the (formatted for readability) result:

ts             = 2019-01-14T22:56:30.429582 
tsDate         = Mon Jan 14 23:03:39 EET 2019 
tsDateAsString = 2019-01-14T23:03:39.582

As you can see the ts and tsDateAsString have different times, although they came from the same starting point.

E.g. ts = 22:56:30 but in tsDateAsString = 23:03:39

Why?

回答1:

As a suggestion: whenever you can, use java.time-utilities.

SimpleDateFormat has a special handling for the milliseconds. Everything that is parsed by the S is treated as milliseconds. As long as you deal with 3-digit-milliseconds, everything is fine (you may even just use a single S (i.e. .S) for the milliseconds to parse them), but if you use 6-digit-milliseconds as input then you also get a 6-digit-millisecond(!)-value.

The 6-digit-milliseconds then are actually 3-digit seconds + the 3-digit milliseconds. That is where the deviation is coming from.

How to solve that? Well either shorten the input time string and lose some precision or use the preferred DateTimeFormatter instead with a pattern matching your input, i.e. yyyy-MM-dd'T'HH:mm:ss.SSSSSS:

val TS_DATE_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSSSSS"
val formatter = DateTimeFormatter.ofPattern(TS_DATE_PATTERN)

val tsDate = formatter.parse(ts) // now the value as you would expect it...

Transforming that to a TimeStamp will work as follows:

Timestamp.valueOf(LocalDateTime.from(tsDate))