Java / Kotlin:为什么Jackson解析日期与SimpleDateFormat不同?

我确定这是某种forms的用户错误,但我不能搞清楚我做错了什么。

我有一个Kotlin数据类,这个类的构造方法如下:

data class CronEvent( @JsonFormat( shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'" ) @JsonProperty("time") val time: Date ) 

这被ObjectMapper填充,接受一个json字符串作为有效载荷。 对于我的unit testing,我有一个SimpleDateFormat对象,我用相同的模式实例化。

 val jsonStream = CronEventTests::class.java.classLoader.getResourceAsStream("CronEventPayload.json") val cronEvent = jsonStreamToCronEvent(jsonStream) // ... val simpleDateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'") val expectedDate = simpleDateFormat.parse("2018-01-15T00:48:43Z") cronEvent.time shouldBe expectedDate 

在我的unit testing中加载的json文件( CronEventPayload.json )具有完全相同的日期字符串( 2018-01-15T00:48:43Z ),但我的测试失败。

 java.lang.AssertionError: expected: Mon Jan 15 00:48:43 MST 2018 but was: Sun Jan 14 17:48:43 MST 2018 Expected :Mon Jan 15 00:48:43 MST 2018 Actual :Sun Jan 14 17:48:43 MST 2018 

他们有相同的输入,并使用相同的日期格式字符串,但他们明显不同。 为什么这两个日期不一样?

@JsonFormat的默认时区是UTC 。 您可以使用注释的timezone属性进行覆盖。

SimpleDateFormat的默认时区是您当地的时区( MST ,从您的输出读取)

确保时区匹配。 您可以添加该行:

 simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); 

就在您的SimpleDateFormat的构建下方。

尽管您的文本格式的日期包含时区(最后的Z ,意思是UTC ),但是您使用的格式只是将Z视为文字字符,而不是将其解释为时区。