将 Java 8 的 LocalDateTime 转换为 Joda 的 LocalDateTime 的简单方法

Easy way to convert Java 8's LocalDateTime to Joda's LocalDateTime

有什么简单的方法可以将 Java 8 的 LocalDateTime 转换为 Joda 的 LocalDateTime?

其中一种方法是将其转换为字符串,然后从该字符串创建 Joda 的 LocalDateTime。

通过千纪元转换(本质上是一个java.util.Date()):

java.time.LocalDateTime java8LocalDateTime = java.time.LocalDateTime.now();

// Separate steps, showing intermediate types
java.time.ZonedDateTime java8ZonedDateTime = java8LocalDateTime.atZone(ZoneId.systemDefault());
java.time.Instant java8Instant = java8ZonedDateTime.toInstant();
long millis = java8Instant.toEpochMilli();
org.joda.time.LocalDateTime jodaLocalDateTime = new org.joda.time.LocalDateTime(millis);

// Chained
org.joda.time.LocalDateTime jodaLocalDateTime =
        new org.joda.time.LocalDateTime(
            java8LocalDateTime.atZone(ZoneId.systemDefault())
                              .toInstant()
                              .toEpochMilli()
        );

// One-liner
org.joda.time.LocalDateTime jodaLocalDateTime = new org.joda.time.LocalDateTime(java8LocalDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());

单行,但很长,所以"easy"?都是相对的。

两种 localDate 类型都包含 (year, month, date),因此只需复制这些值:

public static org.joda.time.LocalDate toJoda(java.time.LocalDate input) {
    return new org.joda.time.LocalDate(input.getYear(),
                                       input.getMonthValue(),
                                       input.getDayOfMonth());
}

稍微短一点的方法:
如果您可以使用 ZoneOffset 而不是 ZoneId,那么代码可能会稍微缩短。

java.time.LocalDateTime java8LDT = java.time.LocalDateTime.now();
org.joda.time.LocalDateTime jodaLDT = new org.joda.time.LocalDateTime(
    java8LDT.toInstant(ZoneOffset.UTC).toEpochMilli()
);

可以通过向 toInstant() 方法提供时区偏移来删除对 atZone() 方法的调用。

更详细的解释
澄清一下,我删除的步骤是创建中间 ZonedDateTime 对象。这部分序列仍然与 Java 8 API 在与 Joda 相关之前。

转换过程首先涉及将Java 8 LocalDateTime 转换为纪元以来的毫秒数。这可以通过几种不同的方式实现。例如在安德烈亚斯的回答中:

LocalDateTime ldt = LocalDateTime.now();
ZonedDateTime zdt = ldt.atZone(ZoneId.systemDefault());
Instant instant = zdt.toInstant();
long millis = instant.toEpochMilli();

或者我的选择:

LocalDateTime ldt = LocalDateTime.now();
Instant instant = ldt.toInstant(ZoneOffset.UTC);
long millis = instant.toEpochMilli();

不同之处在于我跳过了创建 Java 8 ZonedDateTime,而是将时区偏移量传递给 toInstant() 方法。

从这点来看,两个答案是一样的。

org.joda.time.LocalDateTime jodaLocalDateTime = new org.joda.time.LocalDateTime(millis);

注意事项
这在使用不适用夏令时更改的一致偏移量进行转换时效果很好。例如,UTC 始终为 +0:00。如果您需要转换为偏移量可以更改的本地时区,那么您需要使用 atZone()

稍长的答案

同时具有 API(Java 8 和 Joda)的 LocalDateTime 是没有时区的 DateTime。但是,如果您有自纪元以来的毫秒数,那么您需要一个偏移量来导出日期和时间。 Java 8 API 需要显式传入偏移量或时区,而如果传递 none,Joda API 将使用系统默认值。

构建 Joda LocalDateTime 的更精确方法是:

org.joda.time.LocalDateTime jodaLocalDateTime = new org.joda.time.LocalDateTime(millis, DateTimeZone.UTC);

这只会在构建期间使用时区来获取正确的日期和时间。一旦构造函数完成,时区将不会成为对象的一部分,因为 LocalDateTime 没有时区。