具有ISO参数的DateTimeFormat无法正确解析时区

时间:2016-05-09 07:31:17

标签: java spring datetime datetime-format

我有这个控制器,我试图使用mockMVC进行测试

@RequestMapping(value = "/something/{language}", method = RequestMethod.GET, produces = { "application/json", "application/xml" })
    public ResponseEntity<someEntity> getInfo( 
            @PathVariable String language, 
            @DateTimeFormat(iso= DateTimeFormat.ISO.DATE_TIME) @RequestParam(required = false) Date fromDate
    )

所以我希望允许像docs这样的日期格式进行解析: 约会时间 最常见的ISO日期时间格式yyyy-MM-dd&#39; H&H:mm:ss.SSSZ,例如

但是我继续这样做:

处理程序执行导致异常:无法转换类型&#39; java.lang.String&#39;的值要求的类型&#39; java.util.Date&#39 ;;嵌套异常是

org.springframework.core.convert.ConversionFailedException: 
Failed to conv ert from type java.lang.String to type 
@org.springframework.format.annotation.DateTimeFormat 
@org.springframework.web.bind.annotation.RequestParam java.util.Date for value '2015-09-26T01:30:00.000Z'; nested exception is
java.lang.IllegalArgumentException: Unable to parse '2015-09-26T01:30:00.000Z'

据我所知,我没有做错任何事,当然这一定是错的。 任何人都能发光我的坏事吗?我不认为我需要发布更多代码,因为异常确实显示了我正确传递给API的正确值吗?

3 个答案:

答案 0 :(得分:3)

工作原理

您收到的日期是String(HTTP请求是基于文本的),并指示Spring如何通过pattern将其转换为Date对象。

//Spring controller 
@GetMapping
public List<Foobar> find(
   @RequestParam(name = "startDate", required = false)
   @DateTimeFormat(pattern = "YOUR_DATE_PATTERN" or iso="ISO Enum member") //how to convert the date string
   Date startDate {
  return service.find(startDate); //work with the java.util.Date object
}

Spring会将这项任务委托给java.text.DateTimeFormat,因此模式应该是供格式化程序类使用的有效模式。

@DateTimeFormat-模式VS Iso

  • 模式:指定您的模式。将直接传递给格式化程序。
  • Iso:org.springframework.format.annotation.DateTimeFormat.ISO枚举的成员,具有预先构建的日期字符串模式。来自枚举文档:
  

DATE最常见的ISO日期格式yyyy-MM-dd,例如

     

DATE_TIME最常见的ISO日期时间格式yyyy-MM-dd'T'HH:mm:ss.SSSZ,例如

     

NONE表示不应应用基于ISO的格式模式。

     

TIME最常见的ISO时间格式HH:mm:ss.SSSZ,例如

  • 请注意,所有Enum成员(除NONE之外)均使用“ Z”作为时区。

日期模式中的“ Z”是什么意思?

  • 查看日期和时间模式的Javadocs,我们有两个选项来处理时区:

    1. 'Z'Char:RFC 822时区语法(Spring将使用此语法)
zone      =  "UT"  / "GMT"                ; Universal Time
                                        ; North American : UT

        /  "EST" / "EDT"                ;  Eastern:  - 5/ - 4

        /  "CST" / "CDT"                ;  Central:  - 6/ - 5

        /  "MST" / "MDT"                ;  Mountain: - 7/ - 6

        /  "PST" / "PDT"                ;  Pacific:  - 8/ - 7

        /  1ALPHA                       ; Military: Z = UT;
                                        ;  A:-1; (J not used)
                                        ;  M:-12; N:+1; Y:+12

        / ( ("+" / "-") 4DIGIT )        ; Local differential
                                        ;  hours+min. (HHMM)
  1. “ X”字符:ISO 8601时区指示符
  

UTC / GMT时区的时间偏移量(15:00−03:30)或'Z'

问题

  • 如果您选择org.springframework.format.annotation.DateTimeFormat.ISO.DATE_TIME枚举成员,它将使用带有yyyy-MM-dd'T'HH:mm:ss.SSSZ模式和RFC 822语法的时区。

修复

  • 使用相同的模式,但时区使用“ X”(使用ISO 8601语法):

    yyyy-MM-dd'T'HH:mm:ss.SSSX

关于Z时区

  • ISO 8601规定:
  

世界标准时间(UTC)

     

如果时间是世界标准时间,请添加Z   时间过后直接没有空格。 Z是用于的区域标记   零UTC偏移量。因此,“ 09:30 UTC”表示为“ 09:30Z”   或“ 0930Z”。 “ 14:45:15 UTC”将是“ 14:45:15Z”或“ 144515Z”。

     

有时会引用ISO 8601时间表示形式中的Z后缀   设为“祖鲁时间”,因为使用相同的字母来指定   祖鲁时区。但是,ACP 121标准定义了   军事时区没有提及UTC并派生了“祖鲁语   时间”来自格林威治标准时间[27],该时间以前是   国际民事时间标准。

相关链接

答案 1 :(得分:2)

根据DateTimeFormat.ISO.DATE_TIME

  

最常见的ISO日期时间格式yyyy-MM-dd'T'HH:mm:ss.SSSZ,例如   2000-10-31 01:30:00.000-05:00。

Z表示时区值,例如-05:00。

您的字符串值不可解析为2015-09-26T01:30:00.000Z,其中Z必须替换为实际时区值。

例如,2015-09-26T01:30:00.000-04:00ISO.DATE_TIME正确解析

答案 2 :(得分:0)

尝试将参数fromDate作为字符串传递。

我遇到了同样的问题,当我在API调用(我使用Postman)中从双引号(")中解开参数的值时,它有效。您可能必须编码一些字符(即+)。