jackson-modules-java8 icon indicating copy to clipboard operation
jackson-modules-java8 copied to clipboard

ZonedDateTime: ZoneId vs ZoneOffset behaviour

Open armandino opened this issue 2 years ago • 8 comments

This issue is related to serializing ZonedDateTime with a ZoneOffset. When the same value is deserialized, we get back ZonedDateTime with a ZoneId instead. As a result, the seralized and deserialized dates are not equal.

Wanted to confirm whether this is a bug. If not, is there a recommended workaround?

Test case: https://github.com/armandino/jackson-modules-java8-bug-report

armandino avatar Jun 17 '22 21:06 armandino

It would seem ideal if the same representation would be returned with round-trip processing, but perhaps there are technical problems with that. I do not recall this being brought up before. But if it was possible to get the same timezone representation back, that would seem preferable; I do not think change is intentional per se. So PR would be welcome if anyone wants to try it.

But one quick question: is the actual point-in-time still correct? (ignoring the different in representation of the timezone information). If not, that would be a bigger problem.

cowtowncoder avatar Jun 17 '22 22:06 cowtowncoder

Thanks for a quick response. I believe it is the same point in time, however I must admit I don't have an in-depth knowledge of java.time and might be overlooking something.

armandino avatar Jun 17 '22 23:06 armandino

Right, I would expect internal point in time to be same, which is at least some consolation. As to the different in timezone representation, I vaguely recall there being some issues but I would have thought problem would go the other way: inability to retain zone id and only getting offset.

Still, a PR for (failing) test case would be useful; I could check that in (under .../failing/) in case anyone has time to look into what is happening (possibly me, but not necessarily)

cowtowncoder avatar Jun 18 '22 01:06 cowtowncoder

I added a test case #245

armandino avatar Jun 18 '22 04:06 armandino

I looked into this a bit more. Since by default, the date gets serialized into a decimal representation, e.g. {"date":1655571280.545632194}, there's not enough information to determine the original ZoneOffset or ZoneId. As a result, the UTC ZoneId is applied. For example, serializing ZonedDateTime.now(ZoneOffset.ofHours(-7)) and then deserializing produces a date with UTC ZoneId: 2022-06-18T17:11:46.583714647Z[UTC]. I'm not sure if a fix is possible (or needed) for this case.

There is another use case, deserializing dates in string format, such as "2022-06-18T10:11:46.583714647-07:00". Currently this also gets deserialzed as UTC: 2022-06-18T17:11:46.583714647Z[UTC]. However, in this case it should be possible to determine the original representation since ZonedDateTime.parse() can handle such strings automatically:

ZonedDateTime.parse("2022-06-18T10:11:46.583714647-07:00") // => 2022-06-18T10:11:46.583714647-07:00
ZonedDateTime.parse("2022-06-18T17:11:46.583714647Z[UTC]") // => 2022-06-18T17:11:46.583714647Z[UTC]

Then with SerializationFeature.WRITE_DATES_AS_TIMESTAMPS disabled, we should get a ZonedDateTime that is equal to the orginal value, as expected.

I updated the test case to reflect this.

armandino avatar Jun 18 '22 18:06 armandino

see https://github.com/FasterXML/jackson-modules-java8/pull/267 for an in-depth explanation. I think these issues are related. In this case you may want to try disabling DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE. The default timezone in jackson is UTC, and by default the deserializer will adjust the zone to match the context's timezone.

dscalzi avatar Feb 19 '23 23:02 dscalzi

@dscalzi thank you for looking into this. I'll try your suggestion.

armandino avatar Feb 20 '23 07:02 armandino

FWTW, I implemented #281 which allows disabling ZoneId normalization and might help here. Will be included in 2.16.0 release.

cowtowncoder avatar Nov 12 '23 04:11 cowtowncoder