Skip to content

Commit 67e06ee

Browse files
authored
Fix #166: deserialize OffsetDateTime.MIN or OffsetDateTime.MAX with ADJUST_DATES_TO_CONTEXT_TIME_ZONE enabled (#176)
* Do not adjust Time Zone if value is OffsetDateTime.MIN or OffsetDateTime.MAX with ADJUST_DATES_TO_CONTEXT_TIME_ZONE enabled. * deleted private e-mail * Fixing e-mail.
1 parent 0e6702c commit 67e06ee

File tree

4 files changed

+45
-2
lines changed

4 files changed

+45
-2
lines changed

datetime/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ more ambiguous integer types are read as fractional seconds without a decimal po
2323

2424
For TimeZone handling, `ADJUST_DATES_TO_CONTEXT_TIME_ZONE` (default: true) specifies whether the context provided by `java.time.TimeZone`
2525
'SerializedProvider#getTimeZone()' should be used to adjust Date/Time values on deserialization, even if the value itself
26-
contains timezone information. If disabled, it will only be used if the value itself does not contain any TimeZone information.
26+
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.
2727

2828
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
2929
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

datetime/src/main/java/com/fasterxml/jackson/datatype/jsr310/deser/InstantDeserializer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public class InstantDeserializer<T extends Temporal>
7373
OffsetDateTime::from,
7474
a -> OffsetDateTime.ofInstant(Instant.ofEpochMilli(a.value), a.zoneId),
7575
a -> OffsetDateTime.ofInstant(Instant.ofEpochSecond(a.integer, a.fraction), a.zoneId),
76-
(d, z) -> d.withOffsetSameInstant(z.getRules().getOffset(d.toLocalDateTime())),
76+
(d, z) -> (d.isEqual(OffsetDateTime.MIN) || d.isEqual(OffsetDateTime.MAX) ? d : d.withOffsetSameInstant(z.getRules().getOffset(d.toLocalDateTime()))),
7777
true // yes, replace zero offset with Z
7878
);
7979

datetime/src/test/java/com/fasterxml/jackson/datatype/jsr310/deser/OffsetDateTimeDeserTest.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,45 @@ public void testStrictDeserializeFromEmptyString() throws Exception {
656656
objectReader.readValue(valueFromEmptyStr);
657657
}
658658

659+
// [module-java8#166]
660+
@Test
661+
public void testDeserializationNoAdjustIfMIN() throws Exception
662+
{
663+
OffsetDateTime date = OffsetDateTime.MIN;
664+
ObjectMapper m = newMapper()
665+
.configure(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE, true)
666+
.setTimeZone(TimeZone.getTimeZone(Z1))
667+
.addMixIn(Temporal.class, MockObjectConfiguration.class);
668+
Temporal value = m.readValue(
669+
"[\"" + OffsetDateTime.class.getName() + "\",\"" + FORMATTER.format(date) + "\"]", Temporal.class
670+
);
671+
672+
assertNotNull("The value should not be null.", value);
673+
assertTrue("The value should be an OffsetDateTime.", value instanceof OffsetDateTime);
674+
OffsetDateTime actualValue = (OffsetDateTime) value;
675+
assertIsEqual(date, actualValue);
676+
assertEquals(date.getOffset(),actualValue.getOffset());
677+
}
678+
679+
@Test
680+
public void testDeserializationNoAdjustIfMAX() throws Exception
681+
{
682+
OffsetDateTime date = OffsetDateTime.MAX;
683+
ObjectMapper m = newMapper()
684+
.configure(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE, true)
685+
.setTimeZone(TimeZone.getTimeZone(Z1))
686+
.addMixIn(Temporal.class, MockObjectConfiguration.class);
687+
Temporal value = m.readValue(
688+
"[\"" + OffsetDateTime.class.getName() + "\",\"" + FORMATTER.format(date) + "\"]", Temporal.class
689+
);
690+
691+
assertNotNull("The value should not be null.", value);
692+
assertTrue("The value should be an OffsetDateTime.", value instanceof OffsetDateTime);
693+
OffsetDateTime actualValue = (OffsetDateTime) value;
694+
assertIsEqual(date, actualValue);
695+
assertEquals(date.getOffset(),actualValue.getOffset());
696+
}
697+
659698
private static void assertIsEqual(OffsetDateTime expected, OffsetDateTime actual)
660699
{
661700
assertTrue("The value is not correct. Expected timezone-adjusted <" + expected + ">, actual <" + actual + ">.",

release-notes/CREDITS-2.x

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,3 +103,7 @@ Arturas Gusevas (agusevas@github)
103103
Samantha Williamson (samwill@github)
104104
* Contributed fix to #148: Allow strict `LocalDate` parsing
105105
(2.11.0)
106+
107+
Moritz Orth (morth@github.com)
108+
* Reported and suggested fix for #166: Cannot deserialize OffsetDateTime.MIN and
109+
OffsetDateTime.MAX with ADJUST_DATES_TO_CONTEXT_TIME_ZONE enabled (2.12)

0 commit comments

Comments
 (0)