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



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

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

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

所有

ord.joda.time.DateTimeZone.getId()

映射到中可用的id

java.time.ZoneId

如果使用夏令时转换,应避免分别提供每个字段。使用划时代Millis进行转换,如下例所示。

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。在那一天,您有两个02:00的实例,一个较早的实例为GMT+2,另一个较晚的实例为GMT+1。

由于您使用的是ZoneId,而不是偏移,因此无法知道您想要两个实例中的哪一个。默认情况下,在转换过程中假定第一个。如果您提供hourOfDay和ZoneId,02:00 GMT+2和02:00 GMT+1都将转换为02:00 GMT+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();

相关内容

  • 没有找到相关文章