在我看来,绑定到 LocalDate 类型属性的 spring 注释 @DateTimeFormat 将导致 Spring 选择 JodaTime-Formatter,而不是标准格式化程序,否则 Spring 将无法成功将任何输入字符串解析为LocalDate 类型的对象。这条语句是对Spring source code的分析做的(见方法getParser(DateTimeFormat annotation, Class<?> fieldType)的实现)。
如果是这样,那么问题仍然是为什么您的变通方法和解决方案“dd.MM.yy” 能够解析两位数年份以及正常的四位数年份。答案可以在 Joda 资源和文档中找到。
org.joda.time.format.DateTimeFormat 的
源代码摘录(在私有方法 parsePatternTo(DateTimeFormatterBuilder builder, String pattern) 中完成的 JodaTime 模式分析):
case 'y': // year (number)
case 'Y': // year of era (number)
if (tokenLen == 2) {
boolean lenientParse = true;
// Peek ahead to next token.
if (i + 1 < length) {
indexRef[0]++;
if (isNumericToken(parseToken(pattern, indexRef))) {
// If next token is a number, cannot support
// lenient parse, because it will consume digits that it should not.
lenientParse = false;
}
indexRef[0]--;
}
// Use pivots which are compatible with SimpleDateFormat.
switch (c) {
case 'x':
builder.appendTwoDigitWeekyear(new DateTime().getWeekyear() - 30, lenientParse);
break;
case 'y':
case 'Y':
default:
builder.appendTwoDigitYear(new DateTime().getYear() - 30, lenientParse);
break;
}
所以我们认识到 JodaTime 将模式表达式“yy”转换为对构建器方法 appendTwoDigitYear() 的调用,其中参数 lenientParse 设置为 true。有趣的是,所选的枢轴年份偏离了通常的 Joda 设置(+/-50 年),即(-80/+20 年)。
在Javadoc of mentioned builder-method中是这样说的:
"lenientParse - 为真时,如果位数不是两个,则视为绝对年份"
这充分解释了为什么 "dd.mm.yy" 可以将两位数年份解析为四位数年份。