java 使用 Spring Boot 和 Jackson 的日期时区
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/46653455/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Date timezone with Spring boot and Hymanson
提问by Habchi
I'm developing a spring boot application that handles dates. When I submit an Appointment object that has a startDateTime
and an endDateTime
(Both are of type java.util.Date
) I send a format like this:
我正在开发一个处理日期的 Spring Boot 应用程序。当我提交一个具有startDateTime
和的约会对象endDateTime
(两者都是类型java.util.Date
)时,我发送的格式如下:
{
"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",
}
When data is persisted in database it's with the correct timezone, when I try to retrieve my data back, they seem correct when I'm debugging however, once they are serialized by Hymanson I have an output with these as value:
当数据保存在数据库中时,它具有正确的时区,当我尝试取回我的数据时,它们在我调试时似乎是正确的,但是,一旦它们被 Hymanson 序列化,我就会得到一个输出,这些值作为值:
"startDateTime": "2017-10-09T19:43:07.109+0000",
"endDateTime": "2017-10-09T18:40:07.109+0000",
How can I configure Hymanson to make usage of timezone that comes with the data from my repository?
如何配置 Hymanson 以使用存储库中数据附带的时区?
------Update---------
- - - 更新 - - - - -
I tried the answer with OffsetDateTime
but the output is quite weird:
我尝试了答案,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
}
I would like to have something like:
我想要一些类似的东西:
2017-10-09T22:43:07.109+0300
2017-10-09T22:43:07.109+0300
回答by
A java.util.Date
doesn't have any timezone information. Once you deserialize a String
to a Date
, the offset +0300
is lost: the date keeps just the timestamp value, and it can't know what's the original timezone it came from.
Ajava.util.Date
没有任何时区信息。一旦你反序列化String
的Date
,补偿+0300
丢失:日期只保留时间戳值,它可以不知道什么是它来自原来的时区。
If the output must always be in +03:00
offset, you can set it directly in the respective fields, using the com.fasterxml.Hymanson.annotation.JsonFormat
annotation:
如果输出必须始终处于+03:00
偏移量,则可以使用com.fasterxml.Hymanson.annotation.JsonFormat
注释直接在相应字段中进行设置:
@JsonFormat(timezone = "GMT+03:00")
private Date startDateTime;
@JsonFormat(timezone = "GMT+03:00")
private Date endDateTime;
With this, the date fields will always be serialized to +03:00
offset:
这样,日期字段将始终序列化为+03:00
偏移量:
{
"startDateTime":"2017-10-09T22:43:07.109+0300",
"endDateTime":"2017-10-09T21:40:07.109+0300"
}
If the inputs can be in any other offset (not only +03:00
) and you want to preserve it, the java.util.Date
isn't the ideal type. One alternative is to use Hymanson Modules Java 8, if you're using Java >= 8.
如果输入可以在任何其他偏移量中(不仅是+03:00
)并且您想保留它,这java.util.Date
不是理想的类型。如果您使用的是 Java >= 8,另一种选择是使用Hymanson Modules Java8 。
For Java 6 and 7, there's the ThreeTen Backportand the corresponding Hymanson module- I haven't tested, though, but the code might be similar, as the ThreeTen Backport contains the same classes and methods, only the package is different - (in Java 8 is java.time
and in ThreeTen Backport is org.threeten.bp
).
对于 Java 6 和 7,有ThreeTen Backport和相应的Hymanson 模块——不过我没有测试过,但代码可能相似,因为 ThreeTen Backport 包含相同的类和方法,只是包不同——(在Java 8 是java.time
并且在 ThreeTen Backport 中是org.threeten.bp
)。
To preserve the date, time and offset, the best alternative is the OffsetDateTime
class. So you just need to change the fields type and set the corresponding format to it:
要保留日期、时间和偏移量,最好的选择是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;
In the object mapper, you must also register the JavaTimeModule
and disable the ADJUST_DATES_TO_CONTEXT_TIME_ZONE
feature, so the offsets are preserved (the default behaviour is to convert to Hymanson context's timezone, which might not be the same used in the inputs - by disabling this, the offset is preserved).
在对象映射器中,您还必须注册JavaTimeModule
并禁用该ADJUST_DATES_TO_CONTEXT_TIME_ZONE
功能,以便保留偏移量(默认行为是转换为 Hymanson 上下文的时区,这可能与输入中使用的时区不同 - 通过禁用此功能,偏移量是保存)。
You can use a HymansonConfigurator
(as explained in this answer) and do these configurations:
您可以使用HymansonConfigurator
(如本答案中所述)并执行以下配置:
ObjectMapper om = new ObjectMapper();
om.registerModule(new JavaTimeModule());
om.configure(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE, false);
This configuration is usually enough, but you can also set SerializationFeature.WRITE_DATES_AS_TIMESTAMPS
to false
as well, just in case.
这种配置通常是不够的,但你也可以设置SerializationFeature.WRITE_DATES_AS_TIMESTAMPS
到false
为好,以防万一。
If you still need to work with java.util.Date
, you can use the API to convert from/to it. In Java 8, there's the new Date.from
method:
如果您仍然需要使用java.util.Date
,您可以使用 API 来进行转换。在 Java 8 中,有一个新Date.from
方法:
// convert to java.util.Date
public Date getStartAsJavaUtilDate() {
return Date.from(startDateTime.toInstant());
}
And in ThreeTen Backport, there's the org.threeten.bp.DateTimeUtils
class:
在 ThreeTen Backport 中,有这样的org.threeten.bp.DateTimeUtils
课程:
// convert to java.util.Date
DateTimeUtils.toDate(startDateTime.toInstant());
To convert a Date
back to OffsetDateTime
, though, it's more tricky. The Date
object has no timezone information, so it can't know the original offset. One alternative is to keep the original offset in a separate variable:
要转换Date
回OffsetDateTime
,不过,它更棘手。该Date
对象没有时区信息,因此无法知道原始偏移量。一种替代方法是将原始偏移量保留在单独的变量中:
// keep the original offset
ZoneOffset startDateOffset = startDateTime.getOffset();
Then, you can convert the Date
to Instant
, and then convert it to the original offset:
然后,您可以将 转换Date
为Instant
,然后将其转换为原始偏移量:
// convert java.util.Date to original offset (Java 8)
startDateTime = date.toInstant().atOffset(startDateOffset);
// ThreeTen Backport
startDateTime = DateTimeUtils.toInstant(date).atOffset(startDateOffset);