为什么 LocalDateTime.ofInstant() 需要 ZoneId

Why does LocalDateTime.ofInstant() requires ZoneId

提问人:Mike 提问时间:1/26/2023 最后编辑:AnonymousMike 更新时间:1/26/2023 访问量:491

问:

在 Java 中,

  • 如果表示时间点,编码为 世界标准时间。Instant
  • 并表示一个时间点,在 JVM 本地时区中编码为日期和时间。LocalDateTime

那么为什么需要 a 作为第二个参数呢?LocalDateTime.ofInstant()ZoneId

这不仅使人混淆和可能不正确,而且还使其与 ;因为 的时区可以是任何时区,就像 一样。LocalDateTimeZonedDateTimeLocalDateTimeZonedDateTime

日期时间 java-time 本地日期时间 java.time.instant

评论

1赞 Anonymous 1/26/2023
真的没有太多好的用处。我想我一直更喜欢,因为它使时区明确,与.对于确实需要的一种情况,请参阅在 SQL 数据库(如 Postgres 中)中存储约会以用于 java.time 框架LocalDateTimeZonedDateTimeLocalDateTimeLocalDateTime

答:

9赞 Jon Skeet 1/26/2023 #1

并表示一个时间点,在 JVM 本地时区中编码为日期和时间。LocalDateTime

不,这不是真的。无论“编码为”部分如何(我非常怀疑,但我没有重要的知识来反驳),a 并不代表一个时间点。它表示本地日期/时间,不引用特定时区。任何给定都发生在不同时区的不同时间点。LocalDateTimeLocalDateTime

目前欧洲/伦敦时区的当地日期和时间是 2023-01-26T08:50。(比如)美国/New_York的相同时间点将导致不同的.而在美国/New_York,2023-01-26T08:50 的时间点不同。LocalDateTimeLocalDateTime

对于某些/时区组合,可能有零个或两个相应的时间点 - 例如,2022-11-06T01:30 将出现在 America/New_York 2022-11-06 05:30:00Z 和 2022-11-06 06:30:00Z。LocalDateTimeLocalDateTime

希望这足以证明 a 真的不是一个时间点......LocalDateTime

评论

0赞 Anonymous 1/26/2023
可以补充一点,JVM默认时区可以在运行时更改,根据OP的解释,这会导致对象引用不同的时间点。当然,这不是预期的解释。LocalDateTime
5赞 Mark Rotteveel 1/26/2023 #2

LocalDateTime 表示没有时区信息的日期和时间。它用于表示“当地时间”(以我为例,现在当地时间是 2023-01-26 09:50)。Instant 始终为 UTC(例如,现在的时间是 2023-01-26 08:50 UTC)。要在 Instant 和观察者认为的本地时间之间转换,您需要知道观察者位置的 ZoneId(例如,对于我来说是欧洲/阿姆斯特丹),否则您无法派生本地时间。

需要明确的是,LocalDateTime 并不表示时间点(这就是 Instant 的用途)。为了扩展我的例子,对我来说,当地时间 2023-01-26 09:50 现在已经过去了,而对于 Jon Skeet(欧洲/伦敦),当地时间将在不到一个小时的时间内发生)。

1赞 Daxelarne 1/26/2023 #3

.ofInstant()用于指定即时和时区。

如果您不想指定时区和即时时间,则可以使用本地日期和时间。.now()

如果要指定 instant 但不指定 ZoneId,则可以使用 .ZomeId.systemDefault()

1赞 deHaar 1/26/2023 #4

an 与时区或偏移量无关,但 a 不是。虽然它没有 或 ,但它的值部分基于特定区域当前具有的偏移量。InstantLocalDateTimeZoneIdZoneOffset

下面是一个代码示例,其中包含不同的区域,这些区域会导致相同的不同值:Instant

public static void main(String[] args) throws DateTimeParseException {
    // example instant (see output)
    var instant = Instant.now();
    // get the instant with different time zones
    var ldtBerlin = LocalDateTime.ofInstant(instant, ZoneId.of("Europe/Berlin"));
    var ldtCanberra = LocalDateTime.ofInstant(instant, ZoneId.of("Australia/Canberra"));
    var ldtKolkata = LocalDateTime.ofInstant(instant, ZoneId.of("Asia/Kolkata"));
    var ldtLA = LocalDateTime.ofInstant(instant, ZoneId.of("America/Los_Angeles"));
    // print all the results
    System.out.println("Instant " + instant.toEpochMilli() + " in different zones:");
    System.out.println(ldtBerlin + " (Berlin)");
    System.out.println(ldtCanberra + " (Canberra)");
    System.out.println(ldtKolkata + " (Kolkata)");
    System.out.println(ldtLA + " (Los Angeles)");
}

输出:

Instant 1674724841016 in different zones:
2023-01-26T10:20:41.016228 (Berlin)
2023-01-26T20:20:41.016228 (Canberra)
2023-01-26T14:50:41.016228 (Kolkata)
2023-01-26T01:20:41.016228 (Los Angeles)

查看不同的值,这些是区域的本地日期和时间,但没有任何值!您可以使用其他对象,例如 (has zone and offset) 和 (has offset)。他们俩都有一种方法,以防你以后需要......LocalDateTimeZonedDateTimeOffsetDateTimetoLocalDateTime()LocalDateTime