【问题标题】:Easy way to convert Java 8's LocalDateTime to Joda's LocalDateTime将 Java 8 的 LocalDateTime 转换为 Joda 的 LocalDateTime 的简单方法
【发布时间】:2016-01-06 22:10:39
【问题描述】:

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

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

【问题讨论】:

  • 将其转换为 ISO 格式的String 并再次解析。将其转换为自纪元以来的毫秒数
  • 是的。我也是这样做的。
  • 如果你已经使用java.time,为什么还要使用Joda Time?
  • 我在我的应用程序中使用 java.time。我的应用程序依赖于使用 Joda 时间的库。这是我需要这种转换的特殊情况。

标签: java datetime jodatime java-time


【解决方案1】:

通过 epoch millis 转换(本质上是 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());

单行,但很长,那么“容易”吗?都是相对的。

【讨论】:

    【解决方案2】:

    两种 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());
    }
    

    【讨论】:

    • 问题是关于 LocalDateTime,而不是 LocalDate。
    • 这个建议也适用于LocalDateTime,但您需要添加一些额外的代码将毫秒转换为纳秒,反之亦然,因为 Joda 的 LocalDateTime 具有毫秒精度,而 Java 的 LocalDateTime 具有精确到纳秒。
    • 说“你只需要添加额外的代码”没有帮助,也与 OP 的问题无关。
    【解决方案3】:

    稍微短一点的方法:
    如果您可以使用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 转换为自纪元以来的毫秒数。这可以通过几种不同的方式来实现。例如在 Andreas 的回答中:

    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 需要显式传入偏移量或时区,而如果没有传入,Joda API 将使用系统默认值。

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

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

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

    【讨论】:

    • 小心:java8LDT.toInstant(ZoneOffset.UTC).toEpochMilli()导致与java8LDT.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() 不同的结果,因为系统未在 systemDefault UTC 运行!!
    • 你可以通过ZoneId.systemDefault().getRules().getOffset(java8LDT)得到合适的偏移量,但我认为atZone(..).toInstant()...要容易得多。
    • 这只是一个例子!实际上,当您可以直接从 Joda 获取当前时间时,您不会在 Java 8 中调用 .now() 并转换为 Joda。您需要知道适用于 java8LDT 的隐式时区并使用正确的偏移量。我明白为什么这个例子可能会误导。
    • 我不同意您应该始终使用systemDefault()。例如,假设您有一个标准化以 UTC 存储所有时间戳的系统。通过明确指定 UTC,转换其中之一会更安全。如果您使用systemDefault(),那么您的转换可以在一台服务器上运行,但不能在另一台服务器上运行。所选答案有效,因为 now() 将使用默认时区。
    • 当然你不应该总是使用systemDefault(),我从来没有这么说过。
    猜你喜欢
    • 2021-11-26
    • 2014-11-16
    • 2016-04-10
    • 1970-01-01
    • 2015-12-30
    • 2019-01-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多