From b73eebc1560fc2de8498115c7d748701da8fe8c0 Mon Sep 17 00:00:00 2001 From: "Kim, Joo Hyuk" Date: Thu, 13 Mar 2025 22:30:59 +0900 Subject: [PATCH 1/2] Add fix --- .../jsr310/deser/InstantDeserializer.java | 2 +- .../deser/JSR310DateTimeDeserializerBase.java | 6 +++++ .../OffsetDateTimeDeser279Test.java | 26 +++++++++++-------- 3 files changed, 22 insertions(+), 12 deletions(-) rename datetime/src/test/java/com/fasterxml/jackson/datatype/jsr310/{tofix => deser}/OffsetDateTimeDeser279Test.java (55%) diff --git a/datetime/src/main/java/com/fasterxml/jackson/datatype/jsr310/deser/InstantDeserializer.java b/datetime/src/main/java/com/fasterxml/jackson/datatype/jsr310/deser/InstantDeserializer.java index 4f406931..e883f533 100644 --- a/datetime/src/main/java/com/fasterxml/jackson/datatype/jsr310/deser/InstantDeserializer.java +++ b/datetime/src/main/java/com/fasterxml/jackson/datatype/jsr310/deser/InstantDeserializer.java @@ -95,7 +95,7 @@ private static OffsetDateTime decimalToOffsetDateTime(FromDecimalArguments args) public static final InstantDeserializer OFFSET_DATE_TIME = new InstantDeserializer<>( OffsetDateTime.class, DateTimeFormatter.ISO_OFFSET_DATE_TIME, - OffsetDateTime::from, + a -> ZonedDateTime.from(a).toOffsetDateTime(), a -> OffsetDateTime.ofInstant(Instant.ofEpochMilli(a.value), a.zoneId), InstantDeserializer::decimalToOffsetDateTime, (d, z) -> (d.isEqual(OffsetDateTime.MIN) || d.isEqual(OffsetDateTime.MAX) ? d : d.withOffsetSameInstant(z.getRules().getOffset(d.toLocalDateTime()))), diff --git a/datetime/src/main/java/com/fasterxml/jackson/datatype/jsr310/deser/JSR310DateTimeDeserializerBase.java b/datetime/src/main/java/com/fasterxml/jackson/datatype/jsr310/deser/JSR310DateTimeDeserializerBase.java index 8ec7efba..fa4092d0 100644 --- a/datetime/src/main/java/com/fasterxml/jackson/datatype/jsr310/deser/JSR310DateTimeDeserializerBase.java +++ b/datetime/src/main/java/com/fasterxml/jackson/datatype/jsr310/deser/JSR310DateTimeDeserializerBase.java @@ -1,6 +1,7 @@ package com.fasterxml.jackson.datatype.jsr310.deser; import java.io.IOException; +import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; import java.time.format.ResolverStyle; @@ -168,6 +169,11 @@ protected JSR310DateTimeDeserializerBase _withFormatOverrides(Deserialization //a time zone picked up from JsonFormat annotation, otherwise serialization might not work if (formatOverrides.hasTimeZone()) { df = df.withZone(formatOverrides.getTimeZone().toZoneId()); + } else { + // [#279] OffsetDateTimedeserialization fails when using (specific?) date-time pattern #279 + if (pattern.endsWith("'Z'")) { + df = df.withZone(ZoneOffset.UTC); + } } deser = deser.withDateFormat(df); } diff --git a/datetime/src/test/java/com/fasterxml/jackson/datatype/jsr310/tofix/OffsetDateTimeDeser279Test.java b/datetime/src/test/java/com/fasterxml/jackson/datatype/jsr310/deser/OffsetDateTimeDeser279Test.java similarity index 55% rename from datetime/src/test/java/com/fasterxml/jackson/datatype/jsr310/tofix/OffsetDateTimeDeser279Test.java rename to datetime/src/test/java/com/fasterxml/jackson/datatype/jsr310/deser/OffsetDateTimeDeser279Test.java index 02b7869c..4840981e 100644 --- a/datetime/src/test/java/com/fasterxml/jackson/datatype/jsr310/tofix/OffsetDateTimeDeser279Test.java +++ b/datetime/src/test/java/com/fasterxml/jackson/datatype/jsr310/deser/OffsetDateTimeDeser279Test.java @@ -1,4 +1,4 @@ -package com.fasterxml.jackson.datatype.jsr310.tofix; +package com.fasterxml.jackson.datatype.jsr310.deser; import java.time.OffsetDateTime; import java.time.ZoneId; @@ -9,13 +9,13 @@ import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsr310.ModuleTestBase; -import com.fasterxml.jackson.datatype.jsr310.testutil.failure.JacksonTestFailureExpected; import static org.junit.jupiter.api.Assertions.*; -public class OffsetDateTimeDeser279Test extends ModuleTestBase +// [modules-java8#279] OffsetDateTimeDeserializer fails to parse date-time string with 'Z' at the end +public class OffsetDateTimeDeser279Test + extends ModuleTestBase { - // For [modules-java8#279] static class Wrapper279 { OffsetDateTime date; @@ -31,18 +31,22 @@ public void setDate(OffsetDateTime date) { } } - private ObjectMapper MAPPER = newMapper(); + private final ObjectMapper MAPPER = newMapper(); - // For [modules-java8#279] - @JacksonTestFailureExpected @Test - public void testWrapperWithPattern279() throws Exception + public void testWrapperWithPattern279() + throws Exception { - final OffsetDateTime date = OffsetDateTime.now(ZoneId.of("UTC")) + OffsetDateTime date = OffsetDateTime.now(ZoneId.of("UTC")) + .withYear(2025).withMonth(3).withDayOfMonth(13).withHour(13).withMinute(29).withSecond(57).withNano(0) .truncatedTo(ChronoUnit.SECONDS); - final Wrapper279 input = new Wrapper279(date); - final String json = MAPPER.writeValueAsString(input); + Wrapper279 input = new Wrapper279(date); + + // serialization first + String json = MAPPER.writeValueAsString(input); + assertEquals("{\"date\":\"2025-03-13T13:29:57Z\"}", json); + // deserialization second Wrapper279 result = MAPPER.readValue(json, Wrapper279.class); assertEquals(input.date, result.date); } From 5ffe64f27a690102e6fc0908c0d9d79aa597727b Mon Sep 17 00:00:00 2001 From: "Kim, Joo Hyuk" Date: Thu, 13 Mar 2025 22:52:11 +0900 Subject: [PATCH 2/2] Add comment to add review --- .../datatype/jsr310/deser/OffsetDateTimeDeser279Test.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datetime/src/test/java/com/fasterxml/jackson/datatype/jsr310/deser/OffsetDateTimeDeser279Test.java b/datetime/src/test/java/com/fasterxml/jackson/datatype/jsr310/deser/OffsetDateTimeDeser279Test.java index 4840981e..30100a33 100644 --- a/datetime/src/test/java/com/fasterxml/jackson/datatype/jsr310/deser/OffsetDateTimeDeser279Test.java +++ b/datetime/src/test/java/com/fasterxml/jackson/datatype/jsr310/deser/OffsetDateTimeDeser279Test.java @@ -22,7 +22,7 @@ static class Wrapper279 { public Wrapper279(OffsetDateTime d) { date = d; } protected Wrapper279() { } - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'") // public OffsetDateTime getDate() { return date; }