Skip to content

Fix #166: deserialize OffsetDateTime.MIN or OffsetDateTime.MAX with ADJUST_DATES_TO_CONTEXT_TIME_ZONE enabled #176

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion datetime/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ more ambiguous integer types are read as fractional seconds without a decimal po

For TimeZone handling, `ADJUST_DATES_TO_CONTEXT_TIME_ZONE` (default: true) specifies whether the context provided by `java.time.TimeZone`
'SerializedProvider#getTimeZone()' should be used to adjust Date/Time values on deserialization, even if the value itself
contains timezone information. If disabled, it will only be used if the value itself does not contain any TimeZone information.
contains timezone information. If the value is `OffsetDateTime.MIN` or `OffsetDateTime.MAX`, the Date/Time value will not be adjusted. If disabled, it will only be used if the value itself does not contain any TimeZone information.

Finally, there are two features that apply to array handling. `UNWRAP_SINGLE_VALUE_ARRAYS` (default: false) allows auto-conversion from single-element arrays to non-JSON-array
values. If the JSON value contains more than one element in the array, deserialization will still fail. `ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT` (default: false) determines whether empty Array value ("[ ]" in JSON) is accepted
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public class InstantDeserializer<T extends Temporal>
OffsetDateTime::from,
a -> OffsetDateTime.ofInstant(Instant.ofEpochMilli(a.value), a.zoneId),
a -> OffsetDateTime.ofInstant(Instant.ofEpochSecond(a.integer, a.fraction), a.zoneId),
(d, z) -> d.withOffsetSameInstant(z.getRules().getOffset(d.toLocalDateTime())),
(d, z) -> (d.isEqual(OffsetDateTime.MIN) || d.isEqual(OffsetDateTime.MAX) ? d : d.withOffsetSameInstant(z.getRules().getOffset(d.toLocalDateTime()))),
true // yes, replace zero offset with Z
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,45 @@ public void testStrictDeserializeFromEmptyString() throws Exception {
objectReader.readValue(valueFromEmptyStr);
}

// [module-java8#166]
@Test
public void testDeserializationNoAdjustIfMIN() throws Exception
{
OffsetDateTime date = OffsetDateTime.MIN;
ObjectMapper m = newMapper()
.configure(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE, true)
.setTimeZone(TimeZone.getTimeZone(Z1))
.addMixIn(Temporal.class, MockObjectConfiguration.class);
Temporal value = m.readValue(
"[\"" + OffsetDateTime.class.getName() + "\",\"" + FORMATTER.format(date) + "\"]", Temporal.class
);

assertNotNull("The value should not be null.", value);
assertTrue("The value should be an OffsetDateTime.", value instanceof OffsetDateTime);
OffsetDateTime actualValue = (OffsetDateTime) value;
assertIsEqual(date, actualValue);
assertEquals(date.getOffset(),actualValue.getOffset());
}

@Test
public void testDeserializationNoAdjustIfMAX() throws Exception
{
OffsetDateTime date = OffsetDateTime.MAX;
ObjectMapper m = newMapper()
.configure(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE, true)
.setTimeZone(TimeZone.getTimeZone(Z1))
.addMixIn(Temporal.class, MockObjectConfiguration.class);
Temporal value = m.readValue(
"[\"" + OffsetDateTime.class.getName() + "\",\"" + FORMATTER.format(date) + "\"]", Temporal.class
);

assertNotNull("The value should not be null.", value);
assertTrue("The value should be an OffsetDateTime.", value instanceof OffsetDateTime);
OffsetDateTime actualValue = (OffsetDateTime) value;
assertIsEqual(date, actualValue);
assertEquals(date.getOffset(),actualValue.getOffset());
}

private static void assertIsEqual(OffsetDateTime expected, OffsetDateTime actual)
{
assertTrue("The value is not correct. Expected timezone-adjusted <" + expected + ">, actual <" + actual + ">.",
Expand Down
4 changes: 4 additions & 0 deletions release-notes/CREDITS-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,7 @@ Arturas Gusevas (agusevas@github)
Samantha Williamson (samwill@github)
* Contributed fix to #148: Allow strict `LocalDate` parsing
(2.11.0)

Moritz Orth ([email protected])
* Reported and suggested fix for #166: Cannot deserialize OffsetDateTime.MIN and
OffsetDateTime.MAX with ADJUST_DATES_TO_CONTEXT_TIME_ZONE enabled (2.12)