如何转换org.joda.time.DateTime到java.time.ZonedDateTime

And*_*ren 11 java timezone datetime jodatime java-time

我有一个数据源与joda时间DateTime对象存储.我需要将它们转换为java ZonedDateTime对象,保留原始时区.

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

如何把org.joda.time.DateTime转换成java.time.ZonedDateTime?

全部

ord.joda.time.DateTimeZone.getId()

映射到可用的ID

java.time.ZoneId

Jod*_*hen 18

并非所有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));
Run Code Online (Sandbox Code Playgroud)

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

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

ZonedDateTime zdt = dt.toGregorianCalendar().toZonedDateTime();
Run Code Online (Sandbox Code Playgroud)

  • 唯一的区别是ROC,被韩国取代.可以使用`ZoneId.SHORT_IDS`访问EST,HST和MST区域.否则,任何差异都只来自Joda-Time中时区数据库的更高版本. (2认同)

Muh*_*can 10

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

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

否则您将在过渡日期失去一小时.例如,德国于2017年10月29日格林尼治标准时间2点03:00从夏令时(格林尼治标准时间+2)过渡到冬令时(格林尼治标准时间+ 1),格林尼治标准时间+ 2成为02:00.在那一天,您有2个02:00的实例 - 较早的一个GMT + 2和后一个GMT + 1.

由于您使用的是ZoneIds而不是偏移量,因此无法知道您想要的两个实例中的哪一个.默认情况下,在转换期间假定第一个.如果您提供hourOfDayZoneId,格林威治标准时间02:00和格林威治标准时间02:00均将转换为格林威治标准时间02:00 + 2 .