我过去常常使用Spring DateTimeFormat pattern
属性支持Java Date
或Joda Localdate
模式
@DateTimeFormat(pattern = "dd.MM.yyyy")
private LocalDate creationDate;
但我需要支持两种日期模式,例如:
如果用户输入了31/12/1999
或31/12/99
,则他们都可以绑定到相同的值31/12/1999
。是否可以为@DateTimeFormat
定义两种模式?
修改
我尝试将模式更改为
@DateTimeFormat(pattern = "dd.MM.yy")
private LocalDate creationDate;
我发现它可以处理这两种情况(例如,当用户输入31/12/1999
或31/12/99
时)两者都绑定到31/12/1999
。有什么意见吗?
答案 0 :(得分:4)
在我看来,绑定到类型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的 源提取(JodaTime在私有方法parsePatternTo(DateTimeFormatterBuilder builder, String pattern)
中完成的模式分析):
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”转换为对builder-method appendTwoDigitYear()
的调用,并将参数lenientParse设置为true
。有趣的是,选择的支点年份偏离通常的Joda设置(+/- 50年),即(-80 / + 20年)。
在Javadoc of mentioned builder-method中说:
“lenientParse - 如果为true,如果数字计数不是2,则将其视为绝对年份”
这足以解释为什么“dd.mm.yy”也可以将两位数年份解析为四位数年份。
答案 1 :(得分:1)
Spring的DateFormatter的当前实现仅允许设置一个模式。
根据Java Documentation for SimpleDateFormat找到您的编辑内容,使用&#34; yy&#34;导致SimpleDateFormat解释相对于某个世纪的缩写年份。它通过将日期调整为创建SimpleDateFormat实例之前的80年和20年之后来实现此目的。
如果要定义接受列表或一组模式的DateFormatter,而不是在调用其parse方法时调用return getDateFormat(locale).parse(text);
,则必须实现一个实现接口{{1}的CustomDateFormatter }如Spring 3 Field Formatting所述。
而不是模式私有变量的单个String,您将拥有一个字符串列表,您的解析方法将与此StackOverflow Question中的示例类似。
按照Spring 3 Field Formatting中的说明实施Formatter<T>
,然后您可以将模式列表指定为注释。