如何在很长的纪元时间内以毫秒为单位创建Java 8 LocalDate?

Vih*_*ung 182 java datetime java-8 java-time

我有一个外部API返回我的日期为longs,表示自Epoch以来的毫秒数.

使用旧式Java API,我只需用Date它构造一个

Date myDate = new Date(startDateLong)
Run Code Online (Sandbox Code Playgroud)

Java 8 LocalDate/ LocalDateTimeclasses中的等价物是什么?

我有兴趣将长度所代表的时间点转换为long当前本地时区.

Hol*_*ger 356

如果您有自Epoch以来的毫秒数并希望使用当前本地时区将它们转换为本地日期,则可以使用

LocalDate date =
    Instant.ofEpochMilli(longValue).atZone(ZoneId.systemDefault()).toLocalDate();
Run Code Online (Sandbox Code Playgroud)

但请记住,即使系统的默认时区也可能发生变化,因此相同的long值可能会在后续运行中产生不同的结果,即使在同一台机器上也是如此.

此外,请记住LocalDate,与java.util.Date实际上代表的是日期,而不是日期和时间.

否则,您可以使用LocalDateTime:

LocalDateTime date =
    LocalDateTime.ofInstant(Instant.ofEpochMilli(longValue), ZoneId.systemDefault());
Run Code Online (Sandbox Code Playgroud)

  • Epoch 定义为 UTC,因此应与时区无关,因此 ZoneId 应始终为 UTC。 (6认同)
  • 来自我的+1以获得更详细的解释.顺便说一下,即使非系统区域也可以改变(通过tzupdater-tool或jdk-change),因此产生前后不同的结果. (2认同)
  • @Meno Hochschild:我没有专注于硬编码的时区,而是与用户指定的时区进行比较,从配置文件或环境变量中读取,程序员自然认为可能会改变.硬编码时区确实很像系统默认值; 程序员很想到他们永远不会改变...... (2认同)
  • @Demigod `LocalDateTime.ofEpochSecond(...)` 需要一个实际的 `ZoneOffset`,但 `ZoneId.systemDefault()` 返回一个 `ZoneId`。`ZoneId` 可以映射到不同的偏移量,具体取决于您所指的时间点。这就是`LocalDateTime.ofInstant` 为您所做的,根据提供的`Instant` 转换指定的`ZoneId`。 (2认同)
  • @PlexQ 指定的时区与 Epoch 无关,它确实与时区无关,但与生成的“LocalDate”或“LocalDateTime”的语义有关。您可以指定您想要的任何时区,只要与这些结果对象的后续使用保持一致即可。想想当您处理由不同方法创建的多个对象时会发生什么。*local* 日期或日期时间的典型用例包含系统默认时区,例如 `LocalDateTime.now()` ≈ `LocalDateTime.ofInstant(Instant.ofEpochMilli(System.currentTimeMillis()), ZoneId.systemDefault())`... (2认同)

Men*_*ild 35

你可以从Instant.ofEpochMilli(长)开始:

LocalDate date =
  Instant.ofEpochMilli(startDateLong)
  .atZone(ZoneId.systemDefault())
  .toLocalDate();
Run Code Online (Sandbox Code Playgroud)

  • +1显示时区.如果省略,则在确定日期时隐式应用JVM的当前默认时区.在任何特定时刻,随着新的一天在东部早些时候开始,时间在世界各地变化. (5认同)

Abh*_*eet 12

我想我有更好的答案.

new Timestamp(longEpochTime).toLocalDateTime();
Run Code Online (Sandbox Code Playgroud)

  • 我的意思是 - 如果你不介意导入javal.sql.Timestamp,考虑到Java的单片性质,我认为很好,因为它只是JVM的所有部分...但感觉有点臭,但我仍然喜欢它更好它认识到的时代基本上是在UTC. (4认同)
  • @PlexQ Java 不再是单一的。要在使用模块时使用“java.sql.Timestamp”,您必须声明对[模块“java.sql”](https://docs.oracle.com/en/java/javase/17/docs/ api/java.sql/module-summary.html),这将依次引入对“java.xml”和“java.logging”的依赖关系。 (2认同)

Mic*_*fel 7

除了时区和其他东西之外,一个非常简单的替代方案new Date(startDateLong)可能是LocalDate.ofEpochDay(startDateLong / 86400000L)

  • 对于某些人来说,我认为只有这样才有意义,但如果不重新计算每天到底有多少毫秒,我就不确定。就我自己而言,我不太了解这个数字,所以我自动知道它代表什么。 (14认同)
  • 我认为你至少应该解释一下 86400000L 代表什么。 (11认同)
  • 我认为很容易看出它是一天中的毫秒数。 (5认同)
  • `java.util.concurrent.TimeUnit.MILLISECONDS.toDays(startDateLong)` (4认同)

tho*_*est 6

基于@Michael Piefel 答案的简单版本:

LocalDate myDate = LocalDate.ofEpochDay(Duration.ofMillis(epochMillis).toDays());
Run Code Online (Sandbox Code Playgroud)