You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
InstantDeserializer deserializes the nanosecond portion of fractional negative timestamps incorrectly: -1.000000001 deserializes to 1969-12-31T23:59:59.000000001Z instead of 1969-12-31T23:59:58.999999999Z #359
2.15.4 - 2.19 and the current master branch (commit c84b1a9 as of this post).
I have not tested anything earlier than what I plan to use.
Description
Please correct me if I am misguided on how negative fractional representations of timestamps should be parsed into java.time.Instant objects. I expected -1.000000001 to deserialize to 1969-12-31T23:59:58.999999999Z, but currently it deserializes to 1969-12-31T23:59:59.000000001Z.
I assume when "splitting" the fraction into its whole seconds and nanoseconds portions, the negative sign should be distributed to both. In other words: -1.000000001 == -1 + -0.000000001, but instead the behavior appears to be -1.000000001 == -1 + 0.000000001.
Strangely, any scenario where the seconds portion is 0 deserializes as I expect it to. For example, -0.000000001 deserializes to 1969-12-31T23:59:59.999999999Z. For some reason, the distribution of the negativity from seconds to nanoseconds is preserved here.
Adding the following unit test to datetime/src/test/java/tools/jackson/datatype/jsr310/deser/InstantDeserTest.java should demonstrate the issue, where test 4 fails and test 5 succeeds:
The following error is produced when executing the tests:
[ERROR] tools.jackson.datatype.jsr310.deser.InstantDeserTest.testDeserializationAsFloat04 -- Time elapsed: 0.128 s <<< FAILURE!
org.opentest4j.AssertionFailedError: expected: <1969-12-31T23:59:58.999999999Z> but was: <1969-12-31T23:59:59.000000001Z>
at org.junit.jupiter.api@5.11.4/org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:151)
at org.junit.jupiter.api@5.11.4/org.junit.jupiter.api.AssertionFailureBuilder.buildAndThrow(AssertionFailureBuilder.java:132)
at org.junit.jupiter.api@5.11.4/org.junit.jupiter.api.AssertEquals.failNotEqual(AssertEquals.java:197)
at org.junit.jupiter.api@5.11.4/org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:182)
at org.junit.jupiter.api@5.11.4/org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:177)
at org.junit.jupiter.api@5.11.4/org.junit.jupiter.api.Assertions.assertEquals(Assertions.java:1145)
at tools.jackson.datatype.javatime/tools.jackson.datatype.jsr310.deser.InstantDeserTest.testDeserializationAsFloat04(InstantDeserTest.java:121)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
If my assumptions are correct, then the fix appears more complicated than just changing the negativeAdjustment boolean passed to the call to DecimalUtils.extractSecondsAndNanos(BigDecimal, BiFunction, boolean) within the _fromDecimal(DeserializationContext, BigDecimal) function of InstantDeserializer to false since that causes unit test ZonedDateTimeSerTest#testSerializationAsTimestamp01NegativeSeconds to fail.
Related Issues
I believe this is related to the implementation of the fix for issues #304, #69, and #132.
changed the title [-]`InstantDeserializer` deserializes the nanosecond portion of fractional timestamps incorrectly: `-1.000000001` deserializes to `1969-12-31T23:59:59.000000001Z` instead of `1969-12-31T23:59:58.999999999Z`[/-][+]`InstantDeserializer` deserializes the nanosecond portion of fractional negative timestamps incorrectly: `-1.000000001` deserializes to `1969-12-31T23:59:59.000000001Z` instead of `1969-12-31T23:59:58.999999999Z`[/+]on Nov 17, 2025
Activity
JooHyukKim commentedon Feb 25, 2025
@Strongbeard my understanding is same as yours. This is bug.
I filed #360 just so we have reproduction (runnable).
I tried adjusting
DecimalUtils.extractSecondsAndNanos()to get solution, but no luck.Maybe try?
[-]`InstantDeserializer` deserializes the nanosecond portion of fractional timestamps incorrectly: `-1.000000001` deserializes to `1969-12-31T23:59:59.000000001Z` instead of `1969-12-31T23:59:58.999999999Z`[/-][+]`InstantDeserializer` deserializes the nanosecond portion of fractional negative timestamps incorrectly: `-1.000000001` deserializes to `1969-12-31T23:59:59.000000001Z` instead of `1969-12-31T23:59:58.999999999Z`[/+]Fix #359
cowtowncoder commentedon Nov 17, 2025
Fixing with Claude, see #378.
Fix FasterXML#359 (FasterXML#378)