Skip to content
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

Inconsistent serialization/deserialization for OffsetDateTime #53

Closed
bcalmac opened this issue Feb 6, 2018 · 6 comments
Closed

Inconsistent serialization/deserialization for OffsetDateTime #53

bcalmac opened this issue Feb 6, 2018 · 6 comments

Comments

@bcalmac
Copy link

bcalmac commented Feb 6, 2018

With WRITE_DATES_AS_TIMESTAMPS disabled, the serialization of OffsetDateTime preserves the offset, while the deserialization discards it (makes the offset 0 as UTC). The unit test below converts an a OffsetDateTime to JSON and back to OffsetDateTime. It fails because of this inconsistency.

NOTE: The OffsetDateTime corresponds to the same Instant, but it's not equal to the original OffsetDateTime as defined by equals(), which takes the offset into account.

    @Test
    public void offsetDateTimeToJsonAndBack() throws IOException {
        ObjectMapper objectMapper = new ObjectMapper()
                .registerModule(new JavaTimeModule())
                .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);

        OffsetDateTime expected = OffsetDateTime.now();
        String actualString = objectMapper.writeValueAsString(expected);
        System.out.println(actualString); // 2018-02-06T08:37:33.557-08:00
        OffsetDateTime actual = objectMapper.readValue(actualString, OffsetDateTime.class);
        assertEquals(expected, actual);
    }

Failure:

java.lang.AssertionError:
Expected :2018-02-06T08:37:33.557-08:00
Actual   :2018-02-06T16:37:33.557Z

A similar test using parse() and toString() works fine:

    @Test
    public void offsetDateTimeToStringAndBack() {
        OffsetDateTime expected = OffsetDateTime.now();
        String actualString = expected.toString();
        System.out.println(actualString);
        OffsetDateTime actual = OffsetDateTime.parse(actualString);
        assertEquals(expected, actual);
    }
@oliverdozsa
Copy link

Hello.
Could it be the problem?
DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE

@bric3
Copy link

bric3 commented Feb 7, 2019

@oliverdozsa It seems to have done the job. Thanks for the tip !

new ObjectMapper().disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE)

@igorbolic
Copy link

Deserialization feature worked for me. When I'm using the ZonedDateTime I had to enable the SerializationFeature.WRITE_DATES_WITH_ZONE_ID as well:

ObjectMapper mapper = new ObjectMapper()
            .registerModule(new JavaTimeModule())
            .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
            .disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE)
            .enable(SerializationFeature.WRITE_DATES_WITH_ZONE_ID);

@yngvark
Copy link

yngvark commented Mar 11, 2019

Is this by design or a bug? It seems to me as a bug.

To me, having ADJUST_DATES_TO_CONTEXT_TIME_ZONE enabled, I would assume (given the name of that constant) that if my code reads a datetime in timezone +5, but my local timezone is +4, it would get converted to +4. But as @bcalmac shows, it gets converted to +0 / UTC.

Also, the javadoc (https://jar-download.com/javaDoc/com.fasterxml.jackson.core/jackson-databind/2.9.5/com/fasterxml/jackson/databind/DeserializationFeature.html#ADJUST_DATES_TO_CONTEXT_TIME_ZONE) states that

Feature that specifies whether context provided TimeZone (DeserializationContext.getTimeZone() should be used to adjust Date/Time values on deserialization.

It does not state that it gets converted to UTC.

@cowtowncoder
Copy link
Member

"Context time zone" means whatever Jackson-configured timezone is, and by default Jackson DOES NOT use "local time zone" (or offset) but UTC. So if you want to use local tz, configure ObjectMapper with it.

At this point I am not sure there is a problem any more (comments wrt settings appear correct to me), so closing. There are newer issues in this area, but if something is missing, please re-file with up-to-date test.

@spyro2000
Copy link

spyro2000 commented Nov 26, 2020

Stumbled across that today. Caused serious issues for that. Why is the default setting to destroy information in a mapping framework. Took us completely by surprise. Why on earth should 2015-01-23T16:21:00+08:00 be parsed with an Offset of 0 hours BY DEFAULT?

A mapped should always survive a simple roundtrimp value -> json -> value without information be thrown away without reason. That's just plain wrong and another magic setting we have to apply now, just because Jackson decided to just throwing away information rather than trying to preserve it.

Please just use OffsetDateTime.toString() and OffsetDateTime.parse() and everything works as expected.

@FasterXML FasterXML locked as resolved and limited conversation to collaborators Nov 26, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants