Skip to content

Lenient deserialization of LocalDate, LocalDateTime is not time-zone aware #342

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

Closed
hpoettker opened this issue Jan 22, 2025 · 5 comments · Fixed by #354
Closed

Lenient deserialization of LocalDate, LocalDateTime is not time-zone aware #342

hpoettker opened this issue Jan 22, 2025 · 5 comments · Fixed by #354
Labels

Comments

@hpoettker
Copy link
Contributor

hpoettker commented Jan 22, 2025

The deserialization code in LocalDateDeserializer contains lenient logic to also accept strings like 2025-01-21T23:00:00Z and deserialize this to a LocalDate: https://github.com/FasterXML/jackson-modules-java8/blob/2.19/datetime/src/main/java/com/fasterxml/jackson/datatype/jsr310/deser/LocalDateDeserializer.java#L164

The problem is that this example timestamp will always be deserialized to 2025-01-21, although in time zones with a positive offset (e.g. Central European Time = +01:00), this is unexpected and a source of errors for users.

My use case is also a JavaScript client communicating with a Java backend (as motivated in one of the comments in the code) and I appreciate the idea. But I think the conversion should be time-zone aware. Strings ending with Z could e.g. be parsed as Instants which could then be transformed to a LocalDate according to the JVM's default TimeZone or the TimeZone that has been set on the ObjectMapper.

@cowtowncoder
Copy link
Member

LocalDate is by definition non-timezoned. Accepting one is sort of wrong but... users abuse this type and so leniency is given, for better or worse.

But I am not sure why 2025-01-21T23:00:00Z should deserialize as something other than 2025-01-21? Did I misread this?

As far as I know, behavior really should be such that any time portion (and timezone, if one given) would be dropped. I disagree in that timezone should have any effect on abstract Date portion.

@hpoettker
Copy link
Contributor Author

hpoettker commented Jan 22, 2025

Thanks for the quick reply!

I live in time zone offset +01:00, and I have a front-end where dates can be entered (e.g. a birth date). When this is handled with JavaScript's Date, then this will lead for 2025-01-22 to a serialized value of 2025-01-21T23:00:00Z, which is equivalent to 2025-01-22T00:00:00+01:00.

I agree that the time should just be dropped when deserializing to a LocalDate. But at least for my use case, dropping it from the (so to say) OffsetDateTime version of the Instant would make more sense.

@cowtowncoder
Copy link
Member

I don't think I really understand the ask here.

So, with given input I (String) what is the current output Ocurr (as plain Date) and what should it instead be (Oexp)? Ignoring details of intermediate types and such.

@hpoettker
Copy link
Contributor Author

The ask is to have an easy option that allows a time zone to be reflected in the lenient deserialization of LocalDate.

The reasoning is that 2025-01-21T23:00:00Z refers to a specific point in time. But people in Los Angeles and Tokyo do not agree, which calendar day this point in time belongs to. In Los Angeles, it belongs to 2025-01-21, but in Tokyo it belongs to 2025-01-22.

This mapping from a point in time to the corresponding calendar day would be useful to have, at least in lenient mode.

Example 1

The input would be for example

{ "dateOfBirth": "2025-01-21T23:00:00Z" }

and the deserialization target would be

record Record(LocalDate dateOfBirth) {}

Currently, the deserialization fails if leniency is disabled and produces a record with the LocalDate 2025-01-21 otherwise.

When a time zone with an offset of +01:00 or higher is set (like Europe/Berlin or Asia/Tokyo), then the ask is to change the deserialized value to 2025-01-22. With no time zone set or time zones like UTC or America/Los Angeles, the deserialization should continue to produce 2025-01-21.

Example 2

Analogously, we can consider the example

{ "dateOfBirth": "2025-01-22T01:00:00Z" }

With lenient deserialization this currently always produces a LocalDate of 2025-01-22.

With a time zone like UTC, Europe/Berlin, or Asia/Tokyo, the ask is to keep producing this value. But with the time zone America/Los Angeles set, the deserialization should produce 2025-01-21.

@cowtowncoder
Copy link
Member

cowtowncoder commented Jan 25, 2025

Ok, if there was a module configuration setting that allows use of TimeZone, as described, but default to false, I would have no objections. As long as user "opts in" this seems acceptable.

It should be relatively to add this by using JavaTimeFeature enum, add a new entry.
Being API addition, this needs to go in 2.19 branch.

Thank you for working with me here @hpoettker.

@cowtowncoder cowtowncoder added cla-received Marker to denote that there is a CLA for pr 2.19 and removed cla-received Marker to denote that there is a CLA for pr labels Feb 7, 2025
@cowtowncoder cowtowncoder changed the title Lenient deserialization of LocalDate is not time-zone aware Lenient deserialization of LocalDate, LocalDateTime is not time-zone aware Feb 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
2 participants