如何将 org.threeten.bp.OffsetDateTime 转换为 java.time.OffsetDateTime?

How can I convert a org.threeten.bp.OffsetDateTime to java.time.OffsetDateTime?

提问人:Fredrik Rambris 提问时间:1/21/2020 最后编辑:AnonymousFredrik Rambris 更新时间:10/7/2021 访问量:6862

问:

我正在使用一个使用 ThreeTen 日期类型的客户端库(第三方,不是我的,无法更改)。我的项目是 Java 11,使用 Java 8 日期类型。将 ThreeTeen 对象转换为其 Java 8 对应对象的推荐方法是什么?

日期时间 java-time 日期时间转换 threetenbp

评论

0赞 Joachim Sauer 1/21/2020
请注意,转换这些数据库时可能会有细微的差异,因为 AFAIK ThreeTen 使用自己的时区数据库,而 JDK 数据库可能使用不同的时区数据库(可能是 OS 时区数据库或包含 JDK 的数据库,具体取决于操作系统)。你对此无能为力。
2赞 Anonymous 1/25/2020
@JoachimSauer 虽然我不知道这是否属实,但这无关紧要,因为他们没有使用时区。OffsetDateTime
2赞 Joachim Sauer 1/26/2020
@OleV.V.:这是一个很好的观点!关于它是独立的 TZ-DB,甚至还有一个关于更新它的文档页面

答:

6赞 deHaar 1/21/2020 #1

似乎没有内置的方法可以将一个实例转换为另一个实例。

我认为您已经编写了自己的转换器,例如以下之一:

逐个零件转换:

public static java.time.OffsetDateTime convertFrom(org.threeten.bp.OffsetDateTime ttOdt) {
    // convert the instance part by part...
    return java.time.OffsetDateTime.of(ttOdt.getYear(), ttOdt.getMonthValue(),
            ttOdt.getDayOfMonth(), ttOdt.getHour(), ttOdt.getMinute(),
            ttOdt.getSecond(), ttOdt.getNano(),
            // ZoneOffset isn't compatible, create one using the seconds of the given
            java.time.ZoneOffset.ofTotalSeconds(ttOdt.getOffset().getTotalSeconds());
}

解析其他实例的格式化输出:

public static java.time.OffsetDateTime convertFrom(org.threeten.bp.OffsetDateTime ttOdt) {
    // convert the instance by parsing the formatted output of the given instance
    return java.time.OffsetDateTime.parse(
            ttOdt.format(org.threeten.bp.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME));
}

还没有测试哪一个更有效率......

评论

1赞 Fredrik Rambris 1/22/2020
这就是我最终所做的。我希望有一种内置的方式来做到这一点。
1赞 Anonymous 1/25/2020
只是吹毛求疵,如果你真的想在不格式化和解析的情况下逐部分完成它,那么使用可以被视为更一致。你给这两个选项真是太好了。java.time.ZoneOffset.ofTotalSeconds(ttOdt.getOffset().getTotalSeconds())
4赞 Anonymous 1/25/2020 #2

这种需求似乎在设计中没有预见到。对于这个看似简单的要求,没有真正好的和自然的选择。

我喜欢有东西可供选择。deHaar已经提供了两个尽可能好的选择。因此,作为补充,这里有第三个:通过自纪元以来的秒和纳秒进行转换,以及总偏移秒数。

    org.threeten.bp.OffsetDateTime fromThirdParty
            = org.threeten.bp.OffsetDateTime.of(2020, 1, 25, 23, 34, 56, 123456789,
                    org.threeten.bp.ZoneOffset.ofHours(1));

    java.time.Instant jtInstant = java.time.Instant
            .ofEpochSecond(fromThirdParty.toEpochSecond(), fromThirdParty.getNano());
    java.time.ZoneOffset jtOffset = java.time.ZoneOffset.ofTotalSeconds(
            fromThirdParty.getOffset().getTotalSeconds());
    java.time.OffsetDateTime converted
            = java.time.OffsetDateTime.ofInstant(jtInstant, jtOffset);

    System.out.println("From " + fromThirdParty);
    System.out.println("To   " + converted);

此代码片段的输出为:

From 2020-01-25T23:34:56.123456789+01:00
To   2020-01-25T23:34:56.123456789+01:00

可能的优势包括:我们正在传输 3 个数字字段(而 deHaar 的第一次转换为 7 个),从而降低了错误传输错误值的风险。我们仍然避免格式化为字符串并解析回来(这对我来说感觉像是一种浪费,但又好又短)。

请把它包装成一个像 deHaar 那样有好名字的方法。

评论

0赞 deHaar 1/25/2020
伟大!我没有考虑过这个选项......谢谢!
1赞 Anonymous 1/26/2020
@deHaar 第四个选项是通过 和 进行转换。我不想那样做。最好避免.至少转换方式(您的第二个选择)更好。ZonedDateTimeGregorianCalendarGregorianCalendarString
4赞 Prasad 10/7/2021 #3

实际上,使用解析进行转换很简单。我一直在寻找解决方案并登陆了这个线程。经过检查,我认为有一种简单的方法可以在这里发布。

java.time.OffsetDateTime odt = java.time.OffsetDateTime.now();
org.threeten.bp.OffsetDateTime ODT = org.threeten.bp.OffsetDateTime.parse(odt.toString());

同样,转换反之亦然

org.threeten.bp.OffsetDateTime ODT = org.threeten.bp.OffsetDateTime.now();
java.time.OffsetDateTime odt = java.time.OffsetDateTime.parse(ODT.toString());

评论

0赞 Arvind Kumar Avinash 10/7/2021
截至目前,这是此页面上所有答案中最简单和最好的。