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

Mat*_*ers 5 java spring datetime datetime-format

我有这个控制器,我正在尝试使用模拟MVC进行测试

@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
    )
Run Code Online (Sandbox Code Playgroud)

因此,我希望允许像文档中的日期格式一样可解析:DATE_TIME最常见的ISO日期时间格式yyyy-MM-dd'T'HH:mm:ss.SSSZ,例如

但是我继续得到这样的东西:

处理程序执行导致异常:无法将类型“ java.lang.String”的值转换为所需的类型“ java.util.Date”;嵌套异常为

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'
Run Code Online (Sandbox Code Playgroud)

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

lin*_*nil 7

这个怎么运作

您收到日期形式String(HTTP 请求是基于文本的)并指示 Spring 如何通过pattern.

//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
}
Run Code Online (Sandbox Code Playgroud)

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

@DateTimeFormat - 模式 VS Iso

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

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

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

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

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

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

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

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

    1. 'Z' 字符: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)
Run Code Online (Sandbox Code Playgroud)
  1. 'X' 字符:ISO 8601 时区指示符

UTC/GMT 时区的时间偏移 (15:00?03:30) 或“Z”

问题

  • 如果您选择org.springframework.format.annotation.DateTimeFormat.ISO.DATE_TIMEEnum 成员,它将使用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)

如果时间是 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] 派生出“祖鲁时间”,该标准以前用作国际民用时间标准。

相关链接


San*_*eev 3

按照DateTimeFormat.ISO.DATE_TIME

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

其中 aZ代表时区值,例如 -05:00。

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

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