如何从 org.joda.time.DateTime 转换为 java.time.ZonedDateTime
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28877981/
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
How to convert from org.joda.time.DateTime to java.time.ZonedDateTime
提问by Andreas Lundgren
I have a data source with joda time DateTime objects stored. I need to convert them into java ZonedDateTime objects, keeping the original timezone.
我有一个存储了 joda 时间 DateTime 对象的数据源。我需要将它们转换为 java ZonedDateTime 对象,保持原始时区。
It is not sufficient to keep the offset since some DateTime objects represents daily repetitive tasks, and these tasks must occur at a specific time in a specific time zone for every date. They must thus follow the specified TimeZone transitions for example summer and winter time. I cannot tell the final usage of the DateTime objects, so I need to keep the Time Zone information on all objects to be safe.
保留偏移量是不够的,因为某些 DateTime 对象代表每日重复性任务,并且这些任务必须在每个日期的特定时区的特定时间发生。因此,它们必须遵循指定的时区转换,例如夏令时和冬令时。我无法确定 DateTime 对象的最终用途,因此我需要保留所有对象的时区信息以确保安全。
How to convert from org.joda.time.DateTime to java.time.ZonedDateTime?
如何从 org.joda.time.DateTime 转换为 java.time.ZonedDateTime?
Will all
将所有
ord.joda.time.DateTimeZone.getId()
ord.joda.time.DateTimeZone.getId()
map to the id's available in
映射到可用的 ID
java.time.ZoneId
java.time.ZoneId
回答by JodaStephen
Not all time-zone strings from Joda-Time will match java.time
but the vast majority will as they are both based on the IANA tz data. Compare DateTimeZone.getAvailableIDs()
to ZoneId.getAvailableZoneIds()
to determine the mismatch. Additional identifiers can be mapped using ZoneId.of(String, Map)
.
并非来自 Joda-Time 的所有时区字符串都会匹配,java.time
但绝大多数会匹配,因为它们都基于 IANA tz 数据。比较DateTimeZone.getAvailableIDs()
以ZoneId.getAvailableZoneIds()
确定不匹配。可以使用 映射其他标识符ZoneId.of(String, Map)
。
To do the main conversion in the most efficient way, you have to pass in each field:
要以最有效的方式进行主转换,您必须传入每个字段:
ZonedDateTime zdt = ZonedDateTime.ofLocal(
LocalDateTime.of(
dt.getYear(),
dt.getMonthOfYear(),
dt.getDayOfMonth(),
dt.getHourOfDay(),
dt.getMinuteOfHour(),
dt.getSecondOfMinute(),
dt.getMillisOfSecond() * 1_000_000),
ZoneId.of(dt.getZone().getID(), ZoneId.SHORT_IDS),
ZoneOffset.ofTotalSeconds(dt.getZone().getOffset(dt) / 1000));
Note the use of ZoneId.SHORT_IDS
as the Map
in this case.
请注意在这种情况下使用ZoneId.SHORT_IDS
as Map
。
For a simpler solution that handles most use cases, but at lower performance, use this:
对于处理大多数用例但性能较低的更简单的解决方案,请使用:
ZonedDateTime zdt = dt.toGregorianCalendar().toZonedDateTime();
回答by Muhip Tezcan
You should avoid providing each field separately if you are working with daylight saving transitions. Convert using epochMillis instead, as in the following example.
如果您正在使用夏令时转换,则应避免单独提供每个字段。使用 epochMillis 进行转换,如下例所示。
Instant instant = Instant.ofEpochMilli(dt.getMillis());
ZoneId zoneId = ZoneId.of(dt.getZone().getID(), ZoneId.SHORT_IDS);
ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, zoneId);
Otherwise you will lose one hour on the date of transition. For example, Germany transitioned from summer time (GMT+2) to winter time (GMT+1) on 29.10.2017 at 03:00 GMT+2, which becomes 02:00 GMT+1. On that day, you have 2 instances of 02:00 - an earlier one with GMT+2 and a later one with GMT+1.
否则,您将在转换日期损失一小时。例如,德国在 2017 年 10 月 29 日 03:00 GMT+2 从夏令时 (GMT+2) 过渡到冬令时 (GMT+1),变为 02:00 GMT+1。在那一天,您有 2 个 02:00 实例 - 一个较早的 GMT+2 实例和一个较晚的 GMT+1 实例。
Since you are working with ZoneIds and not with offsets, there's no way of knowing which one of the 2 instances you want. By default, the first one is assumed during conversion. Both 02:00 GMT+2 and 02:00 GMT+1 are going to be converted to 02:00 GMT+2 if you provide hourOfDay
along with ZoneId.
由于您使用的是 ZoneIds 而不是偏移量,因此无法知道您想要 2 个实例中的哪一个。默认情况下,在转换过程中采用第一个。如果您hourOfDay
与 ZoneId 一起提供,则 02:00 GMT+2 和 02:00 GMT+1 都将转换为 02:00 GMT+2 。