将 ZonedDateTime 转换为时区的 LocalDateTime

问题描述 投票:0回答:6

我有一个

ZonedDateTime
的对象,其构造如下

ZonedDateTime z = ZonedDateTime.of(LocalDate.now().atTime(11, 30), ZoneOffset.UTC);

如何将其转换为瑞士时区的

LocalDateTime
?预期结果应该是
16 april 2018 13:30

java java-8 timezone datetime-conversion zoneddatetime
6个回答
88
投票

如何将其转换为瑞士时区的LocalDateTime?

您可以将 UTC

ZonedDateTime
转换为瑞士时区的
ZonedDateTime
,但保持相同的时间瞬间,然后根据需要从中获取
LocalDateTime
。我很想把它保留为
ZonedDateTime
,除非你出于其他原因需要它作为
LocalDateTime

ZonedDateTime utcZoned = ZonedDateTime.of(LocalDate.now().atTime(11, 30), ZoneOffset.UTC);
ZoneId swissZone = ZoneId.of("Europe/Zurich");
ZonedDateTime swissZoned = utcZoned.withZoneSameInstant(swissZone);
LocalDateTime swissLocal = swissZoned.toLocalDateTime();

27
投票

它有助于理解 LocalDateTime 和 ZonedDateTime 之间的区别。你真正想要的是一个

ZonedDateTime
。如果您想从字符串表示形式中删除时区,您可以将其转换为
LocalDateTime

您正在寻找的是:

ZonedDateTime swissZonedDateTime = withZoneSameInstant(ZoneId.of("Europe/Zurich"));

LocalDateTime - 这基本上是

Date
Time
的美化字符串表示形式;它与时区无关,这意味着它不代表时间线上的任何时间点

Instant - 这是自 EPOCH 以来经过的时间的毫秒表示。这代表时间轴上的特定时刻

ZonedDateTime - 这也表示时间线上的一个瞬间,但是它将其表示为

Date
Time
以及
TimeZone

下面的代码说明了如何使用所有 3 个。

LocalDateTime localDateTime = LocalDateTime.of(2018, 10, 25, 12, 00, 00);  //October 25th at 12:00pm
ZonedDateTime zonedDateTimeInUTC = localDateTime.atZone(ZoneId.of("UTC")); 
ZonedDateTime zonedDateTimeInEST = zonedDateTimeInUTC.withZoneSameInstant(ZoneId.of("America/New_York")); 
    
System.out.println(localDateTime.toString()); // 2018-10-25T12:00
System.out.println(zonedDateTimeInUTC.toString()); // 2018-10-25T12:00Z[UTC]
System.out.println(zonedDateTimeInEST.toString()); // 2018-10-25T08:00-04:00[America/New_York]

如果您要比较上面两个

Instant
ZonedDateTimes
值,它们将是等效的,因为它们都指向同一时刻。格林威治(UTC 时区)某处,10 月 25 日中午;同时,在纽约,时间为上午 8 点(美国/纽约时区)。


6
投票

试试这个。用您的时区替换美国/中部。

ZonedDateTime z = ZonedDateTime.of(LocalDate.now().atTime(11, 30), ZoneOffset.UTC);

System.out.println(z.withZoneSameInstant(ZoneId.of("US/Central")));

2
投票

另一个似乎更直观的选项是将分区日期转换为即时日期,然后使用 LocalDateTime.ofInstant:

ZonedDateTime zdt = ZonedDateTime.of(LocalDate.now().atTime(11, 30), ZoneOffset.UTC);
ZoneId zId = ZoneId.of("US/Central");
LocalDateTime l = LocalDateTime.ofInstant(zdt.toInstant(), zId);

我更喜欢这个而不是

withZoneSameInstant
,因为该解决方案更加不透明 - 你得到的 ZonedDateTime 必须处于特定的内部状态(正确的时区)。使用
ofInstant
可以用于任何时区的任何 ZonedDateTime。


2
投票

有很多方法可以实现你想要的。其中一些如下:

  1. 将给定的
    ZonedDateTime
    转换为
    Instant
    并从
    LocalDateTime
    导出
    Instant
ZonedDateTime zdtUtc = ZonedDateTime.of(LocalDate.now().atTime(11, 30), ZoneOffset.UTC);

Instant instant = zdtUtc.toInstant();

LocalDateTime ldtSwitzerland = LocalDateTime.ofInstant(instant, ZoneId.of("Europe/Zurich"));

在线演示

  1. 使用
    ZonedDateTime#withZoneSameInstant
    将给定的
    ZonedDateTime
    转换为所需时区的
    ZonedDateTime
    ,然后从
    LocalDateTime
    获取
    ZonedDateTime
ZonedDateTime zdtUtc = ZonedDateTime.of(LocalDate.now().atTime(11, 30), ZoneOffset.UTC);

ZonedDateTime zdtSwitzerland = zdtUtc.withZoneSameInstant(ZoneId.of("Europe/Zurich"));

LocalDateTime ldtSwitzerland = zdtSwitzerland.toLocalDateTime();

在线演示

  1. 将给定的
    ZonedDateTime
    转换为
    Instant
    ,可以使用
    ZonedDateTime
     转换为 
    Instant#atZone
    ,然后从
    LocalDateTime
    中获取
    ZonedDateTime
ZonedDateTime zdtUtc = ZonedDateTime.of(LocalDate.now().atTime(11, 30), ZoneOffset.UTC);

Instant instant = zdtUtc.toInstant();

ZonedDateTime zdtSwitzerland = instant.atZone(ZoneId.of("Europe/Zurich"));

LocalDateTime ldtSwitzerland = zdtSwitzerland.toLocalDateTime();

在线演示

  1. 使用
    DateTimeFormatter
    将给定的
    ZonedDateTime
    格式化为与所需时区相关的日期时间字符串,然后通过解析获得的日期时间字符串来导出
    LocalDateTime
    注意: 此方法仅用于您的学习目的;您应该在生产代码中实现第一种方式(最顶层)。
ZonedDateTime zdtUtc = ZonedDateTime.of(LocalDate.now().atTime(11, 30), ZoneOffset.UTC);

DateTimeFormatter dtfSwitzerland = DateTimeFormatter.ISO_ZONED_DATE_TIME.withZone(ZoneId.of("Europe/Zurich"));
String strZdtSwitzerland = dtfSwitzerland.format(zdtUtc);

LocalDateTime ldt = LocalDateTime
        .from(DateTimeFormatter.ISO_LOCAL_DATE_TIME.parse(strZdtSwitzerland, new ParsePosition(0)));

在线演示

Trail:日期时间了解有关现代日期时间 API 的更多信息。


0
投票

如果尝试上述所有方法后仍然无法像我的情况一样工作。我用以下方法修复了它:

ZonedDateTime.parse("date",DateTimeFormatter.ISO_ZONED_DATE_TIME).toInstant().atZone(ZoneId.systemDefault())
© www.soinside.com 2019 - 2024. All rights reserved.