Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

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

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
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
Projects
None yet
2 participants