使用Spring引导和杰克逊日期时区
我正在开发处理日期的弹簧引导应用程序。当我提交具有startDateTime
和endDateTime
(两者都是java.util.Date
类型的)约会对象我送的格式是这样的:使用Spring引导和杰克逊日期时区
{
"lastName": "Jhon",
"firstName": "Doe",
"email": "[email protected]",
"description": "MyDescription",
"startDateTime": "2017-10-09T22:43:07.109+0300",
"endDateTime": "2017-10-09T21:40:07.109+0300",
}
当数据在数据库坚持它与正确的时区,当我尝试找回我的数据传回,他们似乎正确的,当我在调试然而,一旦被杰克逊系列化我有这些的输出值:
"startDateTime": "2017-10-09T19:43:07.109+0000",
"endDateTime": "2017-10-09T18:40:07.109+0000",
如何配置杰克逊做出自带的时区的使用我的资料库中的数据?
------更新---------
我想答案与OffsetDateTime
但输出是相当奇怪:
"startDateTime": {
"offset": {
"totalSeconds": 7200,
"id": "+02:00",
"rules": {
"fixedOffset": true,
"transitionRules": [],
"transitions": []
}
},
"month": "OCTOBER",
"year": 2017,
"hour": 21,
"minute": 49,
"nano": 654000000,
"second": 15,
"dayOfMonth": 9,
"dayOfWeek": "MONDAY",
"dayOfYear": 282,
"monthValue": 10
}
我想有什么像:
2017-10-09T22:43:07.109 + 0300
甲java.util.Date
doesn't have any timezone information。将String
反序列化为Date
后,将会丢失偏移+0300
:该日期只保留时间戳值,并且无法知道其来源的原始时区是什么。
如果输出必须始终+03:00
偏移,您可以直接在各自领域设置,使用com.fasterxml.jackson.annotation.JsonFormat
注释:
@JsonFormat(timezone = "GMT+03:00")
private Date startDateTime;
@JsonFormat(timezone = "GMT+03:00")
private Date endDateTime;
这样,日期字段将永远被序列化到+03:00
偏移:
{
"startDateTime":"2017-10-09T22:43:07.109+0300",
"endDateTime":"2017-10-09T21:40:07.109+0300"
}
如果输入可以是任何其它偏移量(不仅+03:00
)和你想保留它,java.util.Date
不是理想的类型。一种选择是使用Jackson Modules Java 8,如果你使用的是Java> = 8
对于Java 6和7,还有的ThreeTen Backport和相应的Jackson module - 我没有测试过,虽然,但代码可能是相似,因为ThreeTen Backport包含相同的类和方法,所以只有软件包不同 - (在Java 8中为java.time
,在ThreeTen Backport中为org.threeten.bp
)。
要保存日期,时间和偏移量,最好的选择是OffsetDateTime
类。所以,你只需要改变的字段类型,并设置相应的格式它:
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXX")
private OffsetDateTime startDateTime;
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXX")
private OffsetDateTime endDateTime;
在对象映射,你还必须注册JavaTimeModule
和禁用ADJUST_DATES_TO_CONTEXT_TIME_ZONE
feature,所以偏移被保留(默认行为是转换为Jackson上下文的时区,这可能与输入中使用的时区不同 - 通过禁用此功能,偏移量将保留)。
可以使用JacksonConfigurator
(如explained in this answer),做这些配置:
ObjectMapper om = new ObjectMapper();
om.registerModule(new JavaTimeModule());
om.configure(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE, false);
这种配置通常是不够的,但你也可以设置SerializationFeature.WRITE_DATES_AS_TIMESTAMPS
到false
为好,以防万一。
如果您仍然需要java.util.Date
工作,你可以使用API来/将其转换。在Java 8,有一个新的Date.from
方法:
// convert to java.util.Date
public Date getStartAsJavaUtilDate() {
return Date.from(startDateTime.toInstant());
}
而且在ThreeTen反向移植,还有的org.threeten.bp.DateTimeUtils
类:
// convert to java.util.Date
DateTimeUtils.toDate(startDateTime.toInstant());
要将Date
转换回OffsetDateTime
,不过,它更棘手。 Date
对象没有时区信息,因此无法知道原始偏移量。一种选择是保留原来在一个单独的可变偏移:
// keep the original offset
ZoneOffset startDateOffset = startDateTime.getOffset();
然后,您可以转换Date
到Instant
,然后将其转换为原始偏移:
// convert java.util.Date to original offset (Java 8)
startDateTime = date.toInstant().atOffset(startDateOffset);
// ThreeTen Backport
startDateTime = DateTimeUtils.toInstant(date).atOffset(startDateOffset);
spring.jackson.time-zone配置如何?注释适用于我,而春季配置则不适用。 –
使用DateTime类是更适合这种情况 – CodeIsLife
如果OffsetDateTime字段(如下面的答案中所示),您是否使用了'JsonFormat'注释? – 2017-10-09 19:55:29
是的,我添加了这个注解,但仍然没有工作 – Habchi