如何将 ZonedDateTime 转换为 LocalDateTime?

How to convert ZonedDateTime to LocalDateTime?

提问人:Vinod 提问时间:8/1/2023 最后编辑:Mark RotteveelVinod 更新时间:8/1/2023 访问量:120

问:

我想将本地日期和时间转换为UTC,然后再转换回本地日期和时间,我在互联网上找不到解决方案。我使用了以下代码:

// get local date and time
LocalDateTime localDateTime = LocalDateTime.now();
// print local date time
System.out.println(localDateTime);
// get system time zone / zone id
ZoneId zoneId = ZoneId.systemDefault();
// get UTC time with zone offset
ZonedDateTime zonedDateTime = LocalDateTime.now(ZoneOffset.UTC).atZone(zoneId);
System.out.println(zonedDateTime);
// now I want to convert the UTC with timezone back to local time, 
// but below code is not working  
System.out.println(zonedDateTime.toLocalDateTime());

预期结果

local date and time = 2023-08-01T17:15:10.832796200  
zoned date and time = 2023-08-01T11:45:10.832796200+05:30[Asia/Calcutta]  
local date and time after conversion = 2023-08-01T17:15:10.832796200
Java zoneddatetime

评论

0赞 Ranjan 8/1/2023
你能检查一下这个链接吗 stackoverflow.com/questions/49853999/...
1赞 8/1/2023
zonedDateTime.withZoneSameInstant(ZoneOffset.UTC).toLocalDateTime()
0赞 Vinod 8/1/2023
以下是输出(7:22,预计为18:22) 2023-08-01T18:22:09.103796200 2023-08-01T12:52:09.103796200 2023-08-01T12:52:09.103796200+05:30[亚洲/加尔各答] 2023-08-01T07:22:09.103796200
1赞 deHaar 8/1/2023
我不太明白你为什么要将某些东西转换为另一件东西,然后将其转换回原始事物......这(至少)创建了 3 个对象,尽管第一个对象和第三个对象应该是相等的。为什么不保留第一个呢?
0赞 WJS 8/1/2023
这只是一个学术练习吗?您的用例是什么?这听起来像是一个 XY 问题

答:

2赞 rzwitserloot 8/1/2023 #1

ZonedDateTime zonedDateTime = LocalDateTime.now(ZoneOffset.UTC).atZone(zoneId);

这是可疑代码。这段代码说:

UTC区域现在几点了。所以,在阿姆斯特丹这里是 15:46,但如果我运行它(我们现在处于夏令时,阿姆斯特丹有 +2 偏移量),给我一个本地时间为 13:46 的本地 DT 对象。它没有时区,因为..现在是本地日期时间。LocalDateTime.now(ZoneOffset.UTC)

然后,您将该时间(13:46)“放置”在一个区域中。假设是欧洲/阿姆斯特丹,这段代码让我获得了 2 小时前发生的时间。这没有任何意义,你永远不会想写这段代码。zoneId

您可能想要的是:

LocalDateTime nowAtUtc = LocalDateTime.now(ZoneOffset.UTC);
ZonedDateTime zoned = nowAtUtc.atZone(ZoneOffset.UTC);
ZonedDateTime inAmsterdam = zoned.atZoneSameInstant(ZoneId.of("Europe/Amsterdam"));
System.out.println(inAmsterdam.toLocalDateTime());

上面的代码根据我在荷兰的时钟打印当前时间。

当然,这个确切的片段是没有意义的——为什么要从 A 转换为 B,然后再转换回来?通常,如果你想要一个 LDT,或者如果你想要一个 ZDT,你就会去,只是.但是,我假设你问这个问题是因为你做了一堆你从问题中省略的东西。LocalDateTime.now()ZonedDateTime.now(zoneYouAreInterestedIn);

评论

1赞 Vinod 8/2/2023
为什么从 A 转换到 B 然后再转换回来的答案?是检查我的代码是否正确。我想将 UTC 转换为给定的 zoneId。我到了我犯错误的地方,下面的行帮助了我 ZonedDateTime zoned = nowAtUtc.atZone(ZoneOffset.UTC);非常感谢您的澄清,它有所帮助
0赞 deHaar 8/1/2023 #2

除了@rzwitzerloot的答案......

使用一个确定的时间点作为转换和区域跳跃的基础。

java.time有这样一个确定的时间点:一个Instant

下面是一些示例:

public static void main(String[] args) {
    ZoneId zoneId = ZoneId.of("Asia/Calcutta");
    // get a moment in time (Unix epoch) and use it as base
    Instant now = Instant.now();
    // get the local date and time in your zone based on the instant
    LocalDateTime local = LocalDateTime.ofInstant(now, zoneId);
    System.out.println(local);
    // get the zoned date and time in UTC based on the instant
    ZonedDateTime utc = ZonedDateTime.ofInstant(now, ZoneOffset.UTC);
    System.out.println(utc);
    // get the zoned date and time in your zone based on the instant 
    ZonedDateTime localZone = ZonedDateTime.ofInstant(now, zoneId);
    System.out.println(localZone);
    // extract the local date and time from it
    LocalDateTime backToLocal = localZone.toLocalDateTime();
    // then check for equality
    if (local.equals(backToLocal)) {
        System.out.println(local + " == " + backToLocal);
    } else {
        System.err.println(local + " != " + backToLocal);
    }
}

输出(现在):

2023-08-01T20:14:39.776239
2023-08-01T14:44:39.776239Z
2023-08-01T20:14:39.776239+05:30[Asia/Calcutta]
2023-08-01T20:14:39.776239 == 2023-08-01T20:14:39.776239

我使用了一个修复程序,以便在示例中包含您的修复程序。ZoneId

评论

1赞 Vinod 8/2/2023
非常感谢您的帮助,我现在明白了我犯了错误的地方。