When using the new feature to set a global date pattern for all @RequestParam LocalDate arguments by specifying the property spring.mvc.date-format, which is discussed here, I noticed that the common ISO pattern yyyy-MM-dd does not work.
The exception thrown looks like this:
Failed to convert value of type 'java.lang.String' to required type 'java.time.LocalDate'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [@org.springframework.web.bind.annotation.RequestParam java.time.LocalDate] for value '2018-04-20'; nested exception is java.lang.IllegalArgumentException: Parse attempt failed for value [2018-04-20]
Through debugging, I found that the root cause is this exception:
Text '2018-04-20' could not be parsed: Unable to obtain LocalDate from TemporalAccessor: {DayOfMonth=20, YearOfEra=2018, MonthOfYear=4},ISO of type java.time.format.Parsed
And I also found that the DateTimeFormatter that gets used for parsing is represented like that by toString():
Value(YearOfEra,4,19,EXCEEDS_PAD)'-'Value(MonthOfYear,2)'-'Value(DayOfMonth,2)
I _presume_ that the reason why a LocalDate could not be obtained is that the TemporalAccessor that gets constructed lacks a value for the Era field, but has a filled YearOfEra field.
So I tried with uuuu-MM-dd instead, which works perfectly. @wilkinsona suspected that this is unintended and a symptom of a bug, therefore this bug report.
Thank you, @jo-ka.
Here's a small test that reproduces the behaviour that you have described:
assertThat(new WebConversionService("yyyy-MM-dd").convert("2018-01-01",
java.time.LocalDate.class)).isEqualTo(java.time.LocalDate.of(2018, 1, 1));
As I said in #5523, I think we need to switch from ResolverStyle.STRICT to ResolverStyle.SMART but let's wait for confirmation from @bclozel.
We're going to switch to ResolverStyle.SMART.
Most helpful comment
We're going to switch to
ResolverStyle.SMART.