Java 使用 Jackson 进行 DateTime 反序列化的默认时区(Joda-Time 模块)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20222376/
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
Default timezone for DateTime deserialization with Hymanson (Joda-Time module)
提问by ecbrodie
This question is about deserialization to Joda-TimeDateTimeusing Hymanson-datatype-joda modulefor Hymanson. Is there a default timezone that date strings will be deserialized into? If so, what is it? Is it UTC?
这个问题是关于反序列化到乔达时间日期时间使用Hyman逊的数据类型-乔达模块的Hyman逊。是否存在将日期字符串反序列化为的默认时区?如果是,那是什么?是UTC吗?
I need to ask this because the Hymanson documentation is not specific for Joda-Time DateTime. I found in this article (http://wiki.fasterxml.com/HymansonFAQDateHandling) that Hymanson will assume GMTas the default time zone for deserializing into java.util.Date
or java.util.Calendar
. However, there is no mention of Joda-Time data types in this document. In addition, I specifically need strings to deserialize into DateTime
objects using the UTCtimezone, not GMT: although these two zones are very similar, there are some small differences and therefore GMT will not be feasible for me.
我需要问这个,因为 Hymanson 文档不是特定于 Joda-Time DateTime。我在这篇文章 ( http://wiki.fasterxml.com/HymansonFAQDateHandling) 中发现,Hymanson 将GMT假定为反序列化为java.util.Date
或的默认时区java.util.Calendar
。但是,本文档中没有提及 Joda-Time 数据类型。此外,我特别需要DateTime
使用UTC时区而非 GMT将字符串反序列化为对象:虽然这两个时区非常相似,但存在一些细微差别,因此 GMT 对我来说不可行。
Thank you.
谢谢你。
采纳答案by Redder
The source code for DateTimeDeserializer
shows it uses the timezone from DeserializationContext
which is provided by ObjectMapper
during deserialization. If you look at ObjectMapper
API, you will see there is method for setting the timezone:
源代码DateTimeDeserializer
显示它使用反序列化期间DeserializationContext
提供的时区ObjectMapper
。如果您查看ObjectMapper
API,您会看到有设置时区的方法:
public ObjectMapper setTimeZone(TimeZone tz)
Thus you can use this method to configure your ObjectMapper
and set the timezone to the correct one.
因此,您可以使用此方法来配置您ObjectMapper
的时区并将其设置为正确的时区。
For what concerns the default value, it seems the Javadoc says one thing, but the code shows another.
关于默认值,似乎 Javadoc 说的是一件事,但代码显示的是另一件事。
Javadoc for ObjectMapper.setTimeZone(TimeZone tz)
:
Javadoc 用于ObjectMapper.setTimeZone(TimeZone tz)
:
/**
* Method for overriding default TimeZone to use for formatting.
* Default value used is {@link TimeZone#getDefault()}.
*/
However, the code sets the timezone explicitly on:
但是,代码将时区显式设置为:
protected final static BaseSettings DEFAULT_BASE = new BaseSettings(
...
// TimeZone.getDefault()
TimeZone.getTimeZone("GMT"),
...
So, apparently, it actually uses GMT, and not the default JVM default.
因此,显然,它实际上使用 GMT,而不是默认的 JVM 默认值。
I would say that probably the best choice would be not relying on this and set it by yourself on ObjectMapper.setTimeZone(TimeZone tz)
.
我想说,最好的选择可能不是依赖于此,而是自己将其设置为ObjectMapper.setTimeZone(TimeZone tz)
.
回答by Basil Bourque
UTC versus GMT
UTC 与 GMT
For business apps, there is no practical difference between UTCand GMT. The only difference relates to sub-second resolution and a Leap Secondadded every several years. For science, astronomy, satellite-tracking, and such apps the difference may be significant, but that's rare.
对于商业应用程序,UTC和GMT之间没有实际区别。唯一的区别与亚秒级分辨率和每隔几年增加的闰秒有关。对于科学、天文学、卫星跟踪和此类应用程序,差异可能很大,但这种情况很少见。
Hymanson Defaults to UTC/GMT
Hymanson 默认为 UTC/GMT
I don't know Hymanson. But from looking at the doc you linked, it looks like they serialize either (a) the number of milliseconds since January 1st, 1970, UTC, or (b) a string format, the default being ISO 8601format: "1970-01-01T00:00:00.000+0000". So, to answer your question about time zones, it sounds like by default Hymanson always serializes using UTC (no time zone offset) which is the right way to do it. If you care about the time zone that was in use at that time, you should record that fact (what time zone) in a separate field.
我不认识Hyman逊。但是从查看您链接的文档来看,它们似乎序列化了 (a) 自 1970 年 1 月 1 日,UTC 以来的毫秒数,或 (b) 字符串格式,默认为ISO 8601格式:“1970-01- 01T00:00:00.000+0000"。因此,要回答您关于时区的问题,听起来Hyman逊默认总是使用 UTC(无时区偏移)进行序列化,这是正确的做法。如果您关心当时使用的时区,您应该在单独的字段中记录该事实(时区)。
Hymanson ? java.util.Date/Calendar ? Joda-Time
Hyman逊?java.util.Date/日历?乔达时间
Both of those serialized values (milliseconds & ISO 8601 string) can be used with constructors for Joda-Time DateTimeinstances.
这两个序列化值(毫秒和 ISO 8601 字符串)都可以与 Joda-Time DateTime实例的构造函数一起使用。
String dateTimeString = "2013-11-22T18:37:55.645+0000";
org.joda.time.DateTime myDateTime = org.joda.time.format.ISODateTimeFormat.dateTime().withZoneUTC().parseDateTime( dateTimeString );
and…
和…
Long millisSinceEpoch = 1385495462L;
org.joda.time.DateTime myDateTime = new org.joda.time.DateTime( millisSinceEpoch );
If you do not have direct access to those serialized values to feed to Joda-Time DateTime constructors, then let Hymanson instantiate java.util.Date/Calendar objects. Feed those java.util.Date/Calendar objects to Joda-Time to instantiate DateTime objects for further work. Joda-Time users do this commonly.
如果您无法直接访问这些序列化值以提供给 Joda-Time DateTime 构造函数,那么让 Hymanson 实例化 java.util.Date/Calendar 对象。将这些 java.util.Date/Calendar 对象提供给 Joda-Time 以实例化 DateTime 对象以供进一步工作。Joda-Time 用户通常会这样做。
org.joda.time.DateTime myDateTime = new org.joda.time.DateTime( someJavaUtilDateFromHymanson );
You can easily convert that UTC time to other time zones in Joda-Time by calling the toDateTime()method and passing the desired time zone.
您可以通过调用toDateTime()方法并传递所需的时区,轻松地将该 UTC 时间转换为 Joda-Time 中的其他时区。
org.joda.time.DateTimeZone kolkataTimeZone = org.joda.time.DateTimeZone.forID( "Asia/Kolkata" );
org.joda.time.DateTime dateTimeInKolkata = myDateTime.toDateTime( kolkataTimeZone );
Joda-Time easily converts back to java.util.Date using the toDatemethod. So do most of your work in Joda-Time, and convert back to java.util.Date to communicate with Hymanson. And when going back to Hymanson, I would switch my DateTimes back to UTC just for good measure.
Joda-Time 可以使用toDate方法轻松转换回 java.util.Date 。因此,在 Joda-Time 中完成大部分工作,然后转换回 java.util.Date 以与 Hymanson 通信。当回到Hyman逊时,我会将我的 DateTimes 切换回 UTC 只是为了更好的衡量。
myDateTime.toDateTime( org.joda.time.DateTimeZone.UTC )
You'll find many examples of the aforementioned Joda-Time operations here on StackOverflow.com.
您可以在 StackOverflow.com 上找到上述 Joda-Time 操作的许多示例。
Just Do It
去做就对了
I suspect you are doing a little too much worrying and not enough coding. Just try a few little experiments passing values in and out of Hymanson and Joda-Time. You'll quickly get the hang of it. I recommend you let Hymanson do whatever it wants to do by default, then manipulate away in Joda-Time. Joda-Time is built for the gnarly problems of date-time, and Hymanson is presumably not. Joda-Time has both constructors and methods to adjust between time zones as desired.
我怀疑你是不是太担心了,编码不够。只需尝试一些小实验,将值传入和传出 Hymanson 和 Joda-Time。你会很快掌握它的窍门。我建议你默认让 Hymanson 做它想做的任何事情,然后在 Joda-Time 中进行操作。Joda-Time 是为处理日期时间的棘手问题而构建的,而 Hymanson 可能不是。Joda-Time 有构造函数和方法可以根据需要在时区之间进行调整。
A Brighter Future
更光明的未来
In Java 8, JSR 310: Date and Time APIbrings Joda-Time-like classes built into the Java platform. Expect to see frameworks like Hymansonupdated to directly work with those new classes while deprecating the ugly java.util.Date/Calendar classes.
在 Java 8 中,JSR 310:日期和时间 API将类似 Joda-Time 的类引入到 Java 平台中。希望看到像Hymanson这样的框架更新为直接使用这些新类,同时弃用丑陋的 java.util.Date/Calendar 类。
It looks like that Hymanson-datatype-joda projectis trying to bring you that kind of convenience now for Joda-Time. But it does not seem necessary to me. You could just convert between java.util.Date/Calendar and Joda-Time as discussed above.
看起来Hymanson-datatype-joda 项目现在正试图为 Joda-Time 带来这种便利。但对我来说似乎没有必要。如上所述,您可以在 java.util.Date/Calendar 和 Joda-Time 之间进行转换。
P.S. The "Wiki" link for that project's documentation fails. So I could not look at their doc.
PS 该项目文档的“Wiki”链接失败。所以我不能看他们的文档。
回答by Neil
From a simple code I found that when Hymanson deserialize to Date object from string it gives UTC if no timezone is mentioned but when instantiated directly then gives default timezonei.e. the timezone of the machine.
从一个简单的代码中,我发现当 Hymanson 从字符串反序列化为 Date 对象时,如果没有提到时区,它会给出 UTC,但是当直接实例化时,则给出默认时区,即机器的时区。
DateTime date = new DateTime(2013, 1, 2, 0, 0) //gives local timezone
Following gives UTC
以下给出UTC
ObjectMapper mapper = new ObjectMapper();
DateTime dt = new DateTime(2013, 1, 2, 0, 0);
String serialized = mapper.writeValueAsString(dt);
DateTime dt1 = mapper.readValue(serialized, DateTime.class); //gives UTC
回答by Vojta
I also struggled with date formats and finally I found solution. I wanted to use format "2016-02-08T12:49:22.876Z"
since it is ISO 8601 and it is used by JavaScript Dateobject. I also wanted to always use UTC time zone.
我也在日期格式上苦苦挣扎,最后我找到了解决方案。我想使用格式,"2016-02-08T12:49:22.876Z"
因为它是 ISO 8601 并且它被 JavaScript日期对象使用。我还想始终使用 UTC 时区。
I found that this can be done using following code:
我发现这可以使用以下代码完成:
final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
final ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setDateFormat(dateFormat);
System.out.println(objectMapper.writeValueAsString(new Date()));
Please note the X
character in format string. It is supported from Java 7 and specifies time zone in ISO 8601. As documented in SimpleDateFormatit produces Z
(instead of +00:00
) if time zone offset is 0 (UTC).
请注意X
格式字符串中的字符。它受 Java 7 支持并在 ISO 8601 中指定时区。如SimpleDateFormat 中所述,如果时区偏移量为 0 (UTC),它会生成Z
(而不是+00:00
)。