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

Comment From: membersound

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

Comment From: sbrannen

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?

Comment From: membersound

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.

Comment From: sbrannen

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.

Comment From: sbrannen

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?

Comment From: membersound

That's really a great idea. Well done!

Comment From: sbrannen

Current work on this can be viewed in my feature branch: https://github.com/spring-projects/spring-framework/compare/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;