多个模式的绑定日期

时间:2014-02-12 11:05:33

标签: spring date spring-mvc jodatime date-format

我过去常常使用Spring DateTimeFormat pattern属性支持Java DateJoda Localdate模式

@DateTimeFormat(pattern = "dd.MM.yyyy")
private LocalDate creationDate;

但我需要支持两种日期模式,例如:

如果用户输入了31/12/199931/12/99,则他们都可以绑定到相同的值31/12/1999。是否可以为@DateTimeFormat定义两种模式?

修改

我尝试将模式更改为

@DateTimeFormat(pattern = "dd.MM.yy")
private LocalDate creationDate;

我发现它可以处理这两种情况(例如,当用户输入31/12/199931/12/99时)两者都绑定到31/12/1999。有什么意见吗?

2 个答案:

答案 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>,然后您可以将模式列表指定为注释。