I have following code snippet:
final Date d = format.parse(value);
LOGGER.debug("Compare:\nOriginal: {}, Format: {}, Result: {}", value, format.toPattern(), d);
return d;
value
is a String value from json,
format
is a java.text.SimpleDateFormat,
d
is a Date which is parsed from value
Sometimes it works fine, but sometimes it returns strange dates.
Example from logcat:
D/App: 20:14:47.309 com.example.backend.BackendHelper - Compare: Original: 2016-09-16 13:45:00.000+0200, Format: yyyy-MM-dd HH:mm:ss.SSSZ, Result: Fri Jan 01 05:00:00 GMT+07:00 2016 D/App: 20:14:47.309 com.example.backend.BackendHelper - Compare: Original: 2016-09-16 13:20:00.000+0200, Format: yyyy-MM-dd HH:mm:ss.SSSZ, Result: Fri Jan 01 18:20:00 GMT+07:00 2016 D/App: 20:14:47.338 com.example.backend.BackendHelper - Compare: Original: 2016-09-16 15:20:00.000+0200, Format: yyyy-MM-dd HH:mm:ss.SSSZ, Result: Thu Jan 01 05:00:00 GMT+07:00 1970
As you can see, it returns incorrect Date (wrong year or/and month or/and hour) for the String values which have absolutely the same format and differ from each other only by hour and minutes.
The question is: Why?
Your format pattern is correct. And the locale is not relevant here.
Well, you have also supplied the input in your question so we could investigate if there were any non-printable characters. There aren't (and JSON does not produce such nonsense - very unlikely).
So what is left as explanation for the observed unpredictable behaviour is lack of thread-safety. SimpleDateFormat
is not thread-safe, unfortunately (and has also many other disadvantages). So storing only one instance of SimpleDateFormat
as static class field is indeed dangerous.
How to circumvent this limitation of SimpleDateFormat
?
SimpleDateFormat
-object into a ThreadLocal
(better)FastDateFormat
(performance comparable to ThreadLocale-solution, the prefix "Fast" is nowadays a little bit outdated)java.time
incorporated in Java-8), offers an immutable parser), example: OffsetDateTime.parse(input, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSZ"))
DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss.SSSZ").parseDateTime(input)
ChronoFormatter.ofMomentPattern("yyyy-MM-dd HH:mm:ss.SSSZ", PatternType.CLDR, Locale.ROOT, ZonalOffset.UTC).parse(input)
Choosing an immutable formatter/parser is certainly the best and most modern way to go in a multi-thread-environment. For Android, the libraries Apache Commons and ThreetenABP are more compact than the quicker alternatives Joda-Time or Time4A. You have to make your own evaluation what is more important for you, either size or Performance (or maybe other features you need).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With