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;