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

Support fallback parsing patterns in @DateTimeFormat #20292

Closed
spring-projects-issues opened this issue Jul 5, 2017 · 7 comments
Closed

Support fallback parsing patterns in @DateTimeFormat #20292

spring-projects-issues opened this issue Jul 5, 2017 · 7 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Jul 5, 2017

member sound opened SPR-15736 and commented

It would be nice if one could set multiple formats for:

@DateTimeFormat(pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyyMMdd")
@DateTimeFormat(pattern = "yyyy.MM.dd")
private LocalDate date;

https://docs.oracle.com/javase/tutorial/java/annotations/repeating.html


No further details from SPR-15736

@spring-projects-issues spring-projects-issues added status: waiting-for-triage An issue we've not yet triaged or decided on type: enhancement A general enhancement in: core Issues in core modules (aop, beans, core, context, expression) and removed type: enhancement A general enhancement labels Jan 11, 2019
@membersound
Copy link

membersound commented Feb 24, 2021

Is this ever to come? It would be useful to support multiple date patterns on the same field.

@sbrannen
Copy link
Member

How would you envision that working?

Would Spring iterate over the patterns in declaration order and attempt to parse an incoming string using each @DateTimeFormat configuration until one succeeds, failing if none succeed?

@sbrannen sbrannen added the status: waiting-for-feedback We need additional information before we can continue label Feb 24, 2021
@sbrannen sbrannen changed the title Support Repeating Annotations for @DateTimeFormat [SPR-15736] Support @DateTimeFormat as a repeatable annotation [SPR-15736] Feb 24, 2021
@membersound
Copy link

membersound commented Feb 24, 2021

That's how I would expect it, yes.

As workaround for now, I registered a custom Formatter for LocalDate, and inside evaluate different date pattern one by one, taking the first success for granted.

@Configuration
public class Config implements WebMvcConfigurer {
	@Override
	pubic void addFormatters(FormatterRegistry r) {
		r.addFormatterForFieldType(LocalDate.class, new LocalDateFormatter());
	}
}


class LocalDateFormatter implements Formatter<LocalDate> {
	private final DateTimeFormatter PATTERN_ISO = DateTimeFormatter.ofPattern("yyyy-MM-dd");
	private final DateTimeFormatter PATTERN_DE = DateTimeFormatter.ofPattern("dd.MM.yyyy");
	
	@Override
	public LocalDate parse(String text, Locale locale) {
		if (StringUtils.isBlank(text)) return null;
		if (text.contains(".")) return LocalDate.parse(text, PATTERN_DE);
                //some more patterns.
		return LocalDate.parse(text, PATTERN_ISO);
	}
}

But it would be nice simply having the same feature by repeating annotations.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Feb 24, 2021
@sbrannen
Copy link
Member

But it would be nice simply having the same feature by repeating annotations.

I agree that such a feature would be "nice to have".

Unfortunately, it does not appear to be straightforward to support... simply due to the fact that the entire infrastructure around AnnotationFormatterFactory is based on the assumption that there is a single annotation to be processed.

@sbrannen sbrannen added type: enhancement A general enhancement and removed status: feedback-provided Feedback has been provided labels Feb 25, 2021
@sbrannen
Copy link
Member

After some brainstorming with the team, we have come up with an alternative approach to this:

@DateTimeFormat(patterns = { "yyyy-MM-dd", "yyyyMMdd", "yyyy.MM.dd" })
private LocalDate date;

That would be made possible via a new String[] patterns() attribute in @DateTimeFormat that can be used instead of the String pattern() attribute. Note that we would not support multiple values for the iso and style attributes.

This alternative approach allows multiple patterns to be processed with the existing AnnotationFormatterFactory infrastructure -- for example, by updating DateTimeFormatAnnotationFormatterFactory.getFormatter(DateTimeFormat, Class<?>) and DateFormatter to support multiple patterns.

@membersound, what do you think about that?

@sbrannen sbrannen added the status: waiting-for-feedback We need additional information before we can continue label Feb 26, 2021
@membersound
Copy link

That's really a great idea. Well done!

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Feb 26, 2021
@sbrannen sbrannen removed the status: feedback-provided Feedback has been provided label Feb 28, 2021
@sbrannen sbrannen changed the title Support @DateTimeFormat as a repeatable annotation [SPR-15736] Support multiple patterns in @DateTimeFormat [SPR-15736] Feb 28, 2021
@sbrannen sbrannen self-assigned this Feb 28, 2021
@sbrannen sbrannen removed the status: waiting-for-triage An issue we've not yet triaged or decided on label Mar 1, 2021
@sbrannen sbrannen added this to the 5.3.5 milestone Mar 1, 2021
@sbrannen
Copy link
Member

sbrannen commented Mar 2, 2021

Current work on this can be viewed in my feature branch: master...sbrannen:issues/gh-20292-DateTimeFormat-patterns

The current approach is to introduce a new String[] fallbackPatterns() attribute that allows the user to specify a primary pattern for printing and parsing (via the existing style, iso, and pattern attributes) with multiple fallback patterns for parsing if the primary parsing pattern fails.

An example taken from the test suite:

@DateTimeFormat(pattern = "yyyy-MM-dd", fallbackPatterns = { "M/d/yy", "yyyyMMdd", "yyyy.MM.dd" })
private Date dateWithFallbackPatterns;

@sbrannen sbrannen changed the title Support multiple patterns in @DateTimeFormat [SPR-15736] Support fallback parsing patterns in @DateTimeFormat Mar 3, 2021
This was referenced Mar 17, 2021
sbrannen added a commit that referenced this issue Apr 12, 2021
The support for fallback parsing patterns in @DateTimeFormat introduced
in gh-20292 introduced a regression in that the original cause of the
parsing exception was no longer retained.

This commit ensures that the original DateTimeParseException is set as
the cause for any newly created DateTimeParseException, thereby
retaining the original exception as the root cause.

Closes gh-26777
sbrannen added a commit that referenced this issue Apr 16, 2021
The support for fallback parsing patterns in @DateTimeFormat introduced
in gh-20292 introduced a regression in that the original cause of the
parsing exception was no longer retained.

gh-26777 addressed that regression for `java.time` support; whereas,
this commit addresses that regression for legacy Date types.

This commit ensures that the original ParseException is set as the
cause for any newly created ParseException, thereby retaining the
original exception as the root cause.

Closes gh-26804
lxbzmy pushed a commit to lxbzmy/spring-framework that referenced this issue Mar 26, 2022
Prior to this commit, @DateTimeFormat only supported a single format
for parsing date time values via the style, iso, and pattern attributes.

This commit introduces a new fallbackPatterns attribute that can be
used to configure multiple fallback patterns for parsing date time
values. This allows applications to accept multiple input formats for
date time values.

For example, if you wish to use the ISO date format for parsing and
printing but allow for lenient parsing of user input for various
additional date formats, you could annotate a field or method parameter
with configuration similar to the following.

    @DateTimeFormat(
        iso = ISO.DATE,
        fallbackPatterns = { "M/d/yy", "dd.MM.yyyy" }
    )

Closes spring-projectsgh-20292
lxbzmy pushed a commit to lxbzmy/spring-framework that referenced this issue Mar 26, 2022
The support for fallback parsing patterns in @DateTimeFormat introduced
in spring-projectsgh-20292 introduced a regression in that the original cause of the
parsing exception was no longer retained.

This commit ensures that the original DateTimeParseException is set as
the cause for any newly created DateTimeParseException, thereby
retaining the original exception as the root cause.

Closes spring-projectsgh-26777
lxbzmy pushed a commit to lxbzmy/spring-framework that referenced this issue Mar 26, 2022
The support for fallback parsing patterns in @DateTimeFormat introduced
in spring-projectsgh-20292 introduced a regression in that the original cause of the
parsing exception was no longer retained.

spring-projectsgh-26777 addressed that regression for `java.time` support; whereas,
this commit addresses that regression for legacy Date types.

This commit ensures that the original ParseException is set as the
cause for any newly created ParseException, thereby retaining the
original exception as the root cause.

Closes spring-projectsgh-26804
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

3 participants