如何从 org.joda.time.DateTime 转换为 java.time.ZonedDateTime

Posted

技术标签:

【中文标题】如何从 org.joda.time.DateTime 转换为 java.time.ZonedDateTime【英文标题】:How to convert from org.joda.time.DateTime to java.time.ZonedDateTime 【发布时间】:2015-05-06 19:55:11 【问题描述】:

我有一个存储了 joda 时间 DateTime 对象的数据源。我需要将它们转换成 java ZonedDateTime 对象,保持原来的时区。

仅保留偏移量是不够的,因为某些 DateTime 对象代表日常重复性任务,并且这些任务必须在每个日期的特定时区的特定时间发生。因此,它们必须遵循指定的 TimeZone 转换,例如夏季和冬季时间。我无法知道 DateTime 对象的最终用途,因此我需要保留所有对象的时区信息以确保安全。

如何将 org.joda.time.DateTime 转换为 java.time.ZonedDateTime?

全部

ord.joda.time.DateTimeZone.getId()

映射到可用的 id

java.time.ZoneId

【问题讨论】:

另见:***.com/questions/45348503/… 【参考方案1】:

如果您使用夏令时转换,则应避免单独提供每个字段。改用 epochMillis 进行转换,如下例所示。

Instant instant = Instant.ofEpochMilli(dt.getMillis());
ZoneId zoneId = ZoneId.of(dt.getZone().getID(), ZoneId.SHORT_IDS);
ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, zoneId);

否则,您将在过渡日期损失一小时。例如,德国在 2017 年 10 月 29 日 03:00 GMT+2 时从夏令时 (GMT+2) 转换为冬令时 (GMT+1),变为 02:00 GMT+1。那天,您有 2 个 02:00 实例 - 一个较早的 GMT+2 实例和一个较晚的 GMT+1 实例。

由于您使用的是 ZoneIds 而不是偏移量,因此无法知道您想要两个实例中的哪一个。默认情况下,在转换期间假定第一个。如果您提供hourOfDay 和 ZoneId,02:00 GMT+2 和 02:00 GMT+1 都将转换为 02:00 GMT+2。

【讨论】:

这应该是公认的答案,它比当前公认的答案更准确,也可能效率更高。你的最后一行是否等同于instant.atZone(zoneId)【参考方案2】:

并非来自 Joda-Time 的所有时区字符串都会匹配 java.time,但绝大多数会匹配,因为它们都基于 IANA tz 数据。比较 DateTimeZone.getAvailableIDs()ZoneId.getAvailableZoneIds() 以确定不匹配。可以使用ZoneId.of(String, Map) 映射其他标识符。

要以最有效的方式进行主转换,您必须传入每个字段:

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));

注意在这种情况下使用ZoneId.SHORT_IDS 作为Map

对于处理大多数用例但性能较低的更简单的解决方案,请使用:

ZonedDateTime zdt = dt.toGregorianCalendar().toZonedDateTime();

【讨论】:

是否有一个特定的子集不在其中?也许是一些较旧的 POSIX 兼容区域?我希望所有现代Area/Locality 风格的区域都可以在两者中使用。 唯一不同的是ROC,被ROK代替了。可以使用ZoneId.SHORT_IDS 访问 EST、HST 和 MST 区域。否则,任何差异都只是来自 Joda-Time 中的时区数据库的更高版本。 @JodaStephen 代替ZoneId.of(dt.getZone().getID(), ZoneId.SHORT_IDS)) 不是dt.toTimeZone().toZoneId() 也可以工作吗?它似乎将细节分别留给了 JodaTime 和 Java。 这在 DST 更改时无法正常工作((year, month, day, hour, minute, second, millis, zone) 未定义时间点)。 @MuhipTezcan 的回答似乎是正确的。 修复了通过传入偏移量来处理夏令时

以上是关于如何从 org.joda.time.DateTime 转换为 java.time.ZonedDateTime的主要内容,如果未能解决你的问题,请参考以下文章

如何将数据从回收器适配器发送到片段 |如何从 recyclerview 适配器调用片段函数

如何从 Firebase 获取所有设备令牌?

如何直接从类调用从接口继承的方法?

如何从服务器获取和设置 android 中的 API(从服务器获取 int 值)?如何绑定和实现这个

如何从Mac从android studio中的fabric注销? [复制]

如何从设备中获取 PDF 文件以便能够从我的应用程序中上传?