jackson-modules-java8: Missing milliseconds, when parsing Java 8 date-time, if they are zeros
Issue explained here: https://stackoverflow.com/questions/47502158/force-milliseconds-when-serializing-instant-to-iso8601-using-jackson
Version: 2.9.5
How to reproduce: Project where I use Spring Boot 2.0.0.M6, Spring Framework 5.0.1.RELEASE and Jackson 2.9.5
Test 1: Serialize Instant with milliseconds set to 000
:
- Initialize Instant field using
Instant.parse("2017-09-14T04:28:48.000Z")
- Serialize it using Jackson
- Output will be
"2017-09-14T04:28:48Z"
Test 2: Serialize Instant with milliseconds set to some non-000
value:
- Initialize Instant field using
Instant.parse("2017-09-14T04:28:48.100Z")
- Serialize it using Jackson
- Output will be
"2017-09-14T04:28:48.100Z"
Questions:
- Is that behavior by design?
- Is there anything I can do to force serialization of
000
?
About this issue
- Original URL
- State: open
- Created 6 years ago
- Reactions: 34
- Comments: 20 (3 by maintainers)
@beamerblvd I disagree. The ObjectMapper, when explicitly asked to serialize with nanosecond precision, should not trim millis.
Finally circling back to some old issues. Here’s my take on this: The ISO standard in question does not require any particular number of fractional-second digits, and ISO-compliant parsers should be able to handle both the presence and absence of fractional-second digits. Given this, it’s logical to conclude that encoders should not need to export a fixed number of fractional-second digits, because parsers should behave. However, that’s a naive position when you dig a little. Not all parsers are well-behaved. In fact, most aren’t. How many Jackson bugs have we fixed here? A lot.
So … I believe the current behavior is the correct default and should be left as the default in all future versions, but I also believe there should be an option to specify a fixed number of fractional-second digits, in order to accommodate those systems that have issues when there are no fractional-second digits.
This is also a problem for optional sub second precision. Where the trailing zeros are cut off. This seems to be a issue with the deeper dateTimeFormatter.
The issue is if a Json string contains a date with sub second precision such as HH:ss.000000000Z. This is trimmed to just HH:ssZ when it’s converted back into a string.
The omissions of trailing zeros should be optional. But this does not seem to be a Jackson issue.
Has anyone figured out how to make trailing zeros kept using DateTimeFormatterBuilder ? From the looks of the class, the stripping of trailing zeros is always performed.
The goal here should be for the parser date to keep the sub second precision information. Even if there are trailing zeros. Otherwise you can not compare Json string values as the original will have a different string date then what was printed by the parsed version
For me, this breaks sorting and comparisons in Zulu time zone (UTC):
Example:
According to ISO, alphanumeric sort must be equal to chronological sort.
I would like to INSERT Instant.toString() into an SQLite data base, which has no semantic timestamp data type. But:
Workaround: use Instant.plusNanos(1).toString() Example:
This workaround fails of course if the original Instant was 2021-05-19T15:12:40.999999999Z To solve this issue, I now use
This will always set 100 microseconds 000 nanoseconds. But now, I get consistent results:
@StephenOTT I am using something like this:
to get
2021-05-19T15:12:41.330+02:00
And if you would like have more “zeros” like here
2021-05-19T15:12:41.330000+02:00
you can use:But always the last 3 digits will be 0 because OffsetDateTime does not store such a precision
Not exactly what you are looking for maybe, but worth mentioning from one of the links above is the appendInstant(int fractionalDigits) in
DateTimeFormatterBuilder
.I have also encountered this problem. Funny fact and work around is that, using:
Helps to keep zeros like:
2021-05-19T15:12:41.330+02:00
or2021-05-19T15:12:41.300+02:00
Ok. So I am not sure I know everything that goes on here, but let’s see.
So: as to preserving precision: I don’t think this is possible in general, and I don’t think it should be goal of Jackson to try to automatically retain it. If this is important, then system that cares should indicate it with other metadata and probably use custom (de)serializer and/or pre-/post-processor.
However: I am not against having an option to trim / not trim “extra” trailing zeroes, so that whatever JDK offers can be used as-is with predictable behavior (“always include full 9 digits for nanoseconds”).
It’s just a question of
An additional problem, however, is that in some cases JDK also has limitations, and this module uses JDK formatters for most of its functionality.