Skip to content

[695] Fix date deserialization for date-only patterns#696

Merged
jamezp merged 3 commits intoeclipse-ee4j:masterfrom
jamezp:issue695-date-format
Mar 16, 2026
Merged

[695] Fix date deserialization for date-only patterns#696
jamezp merged 3 commits intoeclipse-ee4j:masterfrom
jamezp:issue695-date-format

Conversation

@jamezp
Copy link
Copy Markdown
Member

@jamezp jamezp commented Feb 26, 2026

DateDeserializer previously required both date and time components, causing failures with patterns like yyyy-MM-dd. Now uses parseBest() to handle ZonedDateTime, LocalDateTime, LocalDate, and YearMonth inputs.

resolves #695

Copy link
Copy Markdown
Member

@KyleAure KyleAure left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a good solution to the issue and handles many more time types, but it effectively makes the config property jsonb.zero-time-defaulting obsolete.

I'm a bit new to this project so I am not sure how this has been handled in the past, but it would be a good idea to either: 1. remove this property or 2. make it a no-op and document it. Unless there are any other use cases where you think it would useful?

@jamezp
Copy link
Copy Markdown
Member Author

jamezp commented Feb 26, 2026

Thank you @KyleAure. I left that property alone for compatibility, but you're absolutely right that it doesn't make much sense to keep it. Maybe we should formally deprecate with the reason and make it a no-op.

@jamezp
Copy link
Copy Markdown
Member Author

jamezp commented Feb 27, 2026

@KyleAure I'm considering leaving that off from this fix. When I do that I get some failures locally and I'm a little concerned others might be using this kind of pattern:

[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.438 s <<< FAILURE! -- in org.eclipse.yasson.customization.JsonbDateFormatterTest
[ERROR] org.eclipse.yasson.customization.JsonbDateFormatterTest.testTrimmedDateParsing -- Time elapsed: 0.390 s <<< ERROR!
jakarta.json.bind.JsonbException: Unable to deserialize property 'localDateTime' because of: Error parsing class java.time.LocalDateTime from value: 2018.01.30. Check your @JsonbDateFormat has all time units for class java.time.LocalDateTime type, or consider using org.eclipse.yasson.YassonConfig#ZERO_TIME_PARSE_DEFAULTING.
	at org.eclipse.yasson@3.0.4-SNAPSHOT/org.eclipse.yasson.internal.deserializer.ObjectDeserializer.deserialize(ObjectDeserializer.java:80)
	at org.eclipse.yasson@3.0.4-SNAPSHOT/org.eclipse.yasson.internal.deserializer.ObjectDeserializer.deserialize(ObjectDeserializer.java:31)
	at org.eclipse.yasson@3.0.4-SNAPSHOT/org.eclipse.yasson.internal.deserializer.DefaultObjectInstanceCreator.deserialize(DefaultObjectInstanceCreator.java:57)
	at org.eclipse.yasson@3.0.4-SNAPSHOT/org.eclipse.yasson.internal.deserializer.DefaultObjectInstanceCreator.deserialize(DefaultObjectInstanceCreator.java:29)
	at org.eclipse.yasson@3.0.4-SNAPSHOT/org.eclipse.yasson.internal.deserializer.PositionChecker.deserialize(PositionChecker.java:85)
	at org.eclipse.yasson@3.0.4-SNAPSHOT/org.eclipse.yasson.internal.deserializer.PositionChecker.deserialize(PositionChecker.java:34)
	at org.eclipse.yasson@3.0.4-SNAPSHOT/org.eclipse.yasson.internal.deserializer.NullCheckDeserializer.deserialize(NullCheckDeserializer.java:46)
	at org.eclipse.yasson@3.0.4-SNAPSHOT/org.eclipse.yasson.internal.deserializer.NullCheckDeserializer.deserialize(NullCheckDeserializer.java:26)
	at org.eclipse.yasson@3.0.4-SNAPSHOT/org.eclipse.yasson.internal.DeserializationContextImpl.deserializeItem(DeserializationContextImpl.java:138)
	at org.eclipse.yasson@3.0.4-SNAPSHOT/org.eclipse.yasson.internal.DeserializationContextImpl.deserialize(DeserializationContextImpl.java:127)
	at org.eclipse.yasson@3.0.4-SNAPSHOT/org.eclipse.yasson.internal.JsonBinding.deserialize(JsonBinding.java:56)
	at org.eclipse.yasson@3.0.4-SNAPSHOT/org.eclipse.yasson.internal.JsonBinding.fromJson(JsonBinding.java:63)
	at org.eclipse.yasson@3.0.4-SNAPSHOT/org.eclipse.yasson.customization.JsonbDateFormatterTest.testTrimmedDateParsing(JsonbDateFormatterTest.java:155)
	at java.base/java.lang.reflect.Method.invoke(Method.java:565)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1604)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1604)
Caused by: jakarta.json.bind.JsonbException: Error parsing class java.time.LocalDateTime from value: 2018.01.30. Check your @JsonbDateFormat has all time units for class java.time.LocalDateTime type, or consider using org.eclipse.yasson.YassonConfig#ZERO_TIME_PARSE_DEFAULTING.
	at org.eclipse.yasson@3.0.4-SNAPSHOT/org.eclipse.yasson.internal.deserializer.types.AbstractDateDeserializer.parseWithFormatterInternal(AbstractDateDeserializer.java:125)
	at org.eclipse.yasson@3.0.4-SNAPSHOT/org.eclipse.yasson.internal.deserializer.types.AbstractDateDeserializer.lambda$actualDeserializer$1(AbstractDateDeserializer.java:60)
	at org.eclipse.yasson@3.0.4-SNAPSHOT/org.eclipse.yasson.internal.deserializer.types.AbstractDateDeserializer.deserializeStringValue(AbstractDateDeserializer.java:90)
	at org.eclipse.yasson@3.0.4-SNAPSHOT/org.eclipse.yasson.internal.deserializer.types.TypeDeserializer.deserialize(TypeDeserializer.java:37)
	at org.eclipse.yasson@3.0.4-SNAPSHOT/org.eclipse.yasson.internal.deserializer.ValueExtractor.deserialize(ValueExtractor.java:47)
	at org.eclipse.yasson@3.0.4-SNAPSHOT/org.eclipse.yasson.internal.deserializer.ValueExtractor.deserialize(ValueExtractor.java:24)
	at org.eclipse.yasson@3.0.4-SNAPSHOT/org.eclipse.yasson.internal.deserializer.PositionChecker.deserialize(PositionChecker.java:85)
	at org.eclipse.yasson@3.0.4-SNAPSHOT/org.eclipse.yasson.internal.deserializer.PositionChecker.deserialize(PositionChecker.java:34)
	at org.eclipse.yasson@3.0.4-SNAPSHOT/org.eclipse.yasson.internal.deserializer.NullCheckDeserializer.deserialize(NullCheckDeserializer.java:46)
	at org.eclipse.yasson@3.0.4-SNAPSHOT/org.eclipse.yasson.internal.deserializer.NullCheckDeserializer.deserialize(NullCheckDeserializer.java:26)
	at org.eclipse.yasson@3.0.4-SNAPSHOT/org.eclipse.yasson.internal.deserializer.ObjectDeserializer.deserialize(ObjectDeserializer.java:78)
	... 15 more
Caused by: java.time.format.DateTimeParseException: Text '2018.01.30' could not be parsed: Unable to obtain LocalDateTime from TemporalAccessor: {},ISO resolved to 2018-01-30 of type java.time.format.Parsed
	at java.base/java.time.format.DateTimeFormatter.createError(DateTimeFormatter.java:2079)
	at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:2014)
	at java.base/java.time.LocalDateTime.parse(LocalDateTime.java:496)
	at org.eclipse.yasson@3.0.4-SNAPSHOT/org.eclipse.yasson.internal.deserializer.types.LocalDateTimeDeserializer.parseWithFormatter(LocalDateTimeDeserializer.java:41)
	at org.eclipse.yasson@3.0.4-SNAPSHOT/org.eclipse.yasson.internal.deserializer.types.LocalDateTimeDeserializer.parseWithFormatter(LocalDateTimeDeserializer.java:23)
	at org.eclipse.yasson@3.0.4-SNAPSHOT/org.eclipse.yasson.internal.deserializer.types.AbstractDateDeserializer.parseWithFormatterInternal(AbstractDateDeserializer.java:123)
	... 25 more
Caused by: java.time.DateTimeException: Unable to obtain LocalDateTime from TemporalAccessor: {},ISO resolved to 2018-01-30 of type java.time.format.Parsed
	at java.base/java.time.LocalDateTime.from(LocalDateTime.java:465)
	at java.base/java.time.format.Parsed.query(Parsed.java:247)
	at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:2010)
	... 29 more
Caused by: java.time.DateTimeException: Unable to obtain LocalTime from TemporalAccessor: {},ISO resolved to 2018-01-30 of type java.time.format.Parsed
	at java.base/java.time.LocalTime.from(LocalTime.java:443)
	at java.base/java.time.LocalDateTime.from(LocalDateTime.java:461)
	... 31 more

I see some other issues too, but this would require changing the test. It looks like the failure is on:

@JsonbDateFormat(value = "yyyy.MM.dd")
private LocalDateTime localDateTime;

Which is admittedly a bit odd, but it works now and I'm hesitant to change too much.

That said, if you feel this is worth looking at I think we could probably solve some of these issues without the setting. I just think it will end up being a bigger change.

Copy link
Copy Markdown
Member

@KyleAure KyleAure left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am fine with making the change to the jsonb.zero-time-defaulting property after this fix is merged.
We'll just need to find a committer who can approve this change first. @m0mus?

@jamezp jamezp marked this pull request as draft March 10, 2026 01:01
@jamezp
Copy link
Copy Markdown
Member Author

jamezp commented Mar 10, 2026

I'm temporarily making this a draft as we shouldn't be using the default locale when a locale is not specified. We should be using UTC per the specification. However, that breaks tests given it uses midnight for the start of day and ends up subtracting an hour making the date go back to the previous day.

I just need to look into it and just haven't had the chance yet.

@jamezp jamezp force-pushed the issue695-date-format branch from 8b68cdf to 300556b Compare March 12, 2026 01:30
@jamezp jamezp marked this pull request as ready for review March 12, 2026 01:30
DateDeserializer previously required both date and time components, causing failures with patterns like yyyy-MM-dd. Now uses parseBest() to handle ZonedDateTime, LocalDateTime, LocalDate, and YearMonth inputs.

Signed-off-by: James R. Perkins <jperkins@ibm.com>
@jamezp
Copy link
Copy Markdown
Member Author

jamezp commented Mar 12, 2026

@KyleAure If you wouldn't mind giving this another review. The issue we found was this was failing with -Duser.timezone=Europe/Berlin. This was due to needing to use the UTC offset for date-only patterns given a date doesn't have a timezone. As noted in the JavaDoc though, there is a caveat to this in that the date could display different in the object given a java.util.Date uses the default timezone set.

I tested against the following timezone to ensure we wouldn't have an issue:

  • America/Los_Angeles (my default)
  • Europe/Berlin
  • Asia/Kolkata
  • Pacific/Chatham
  • Asia/Kathmandu
  • Australia/Adelaide
  • Pacific/Kiritimati
  • Pacific/Niue

@jamezp jamezp force-pushed the issue695-date-format branch from 300556b to ad5720c Compare March 12, 2026 01:38
@jamezp jamezp requested a review from KyleAure March 12, 2026 01:38
Copy link
Copy Markdown
Member

@KyleAure KyleAure left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, I appreciate the new tests you wrote.
Just a few suggestions on documentation.

Comment on lines +37 to +39
* <b>Important:</b> Date objects created from date-only patterns represent midnight UTC, which may display as a
* different calendar day when viewed in local timezone. For date values where preserving the local calendar date is
* critical, use {@link java.sql.Date} or better {@link java.time.LocalDate} instead.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this information is better suited to be put either in the JSON-B Javadoc for JsonbDateFormat or somewhere in Section 3.5 of the spec, otherwise I do not expect any user of Yasson to be looking at the javadoc for this class.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I completely agree. I need to file an issue there. I mostly put it here for others looking at why it's done like this.

jamezp and others added 2 commits March 12, 2026 09:59
…ateDeserializer.java

Co-authored-by: Kyle Aure <KyleJAure@gmail.com>
…ateDeserializer.java

Co-authored-by: Kyle Aure <KyleJAure@gmail.com>
@jamezp jamezp merged commit 1ce9680 into eclipse-ee4j:master Mar 16, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Using a pattern the pattern @JsonbDateFormat("yyyy-MM-dd") fails to deserialize a java.util.Date

2 participants