从微秒创建 Java DateTime Instant

DJV*_*ing 3 java java-time java-9 java.time.instant java-11

自 Java 9 以来 Java 日期和时间 API 发生了变化。 LocalDateTime 现在具有微秒精度。

Java 9 具有 java.time.Clock 的全新实现,能够以比毫秒(十进制小数的三位数字)更精细的分辨率捕获当前时刻。

我们从后端服务中获得以微秒为单位的时间。

System.currentTimeMillis  > 1565245051795    > 2019-08-08T06:17:31.795
Service.getTime           > 1565245051795306 > 2019-08-08T06:17:31.795306
Run Code Online (Sandbox Code Playgroud)

为了构造在我们的应用程序中使用的 LocalDateTime,我们执行

long timeMicros = service.getTime();
long timeMillis = timeMicros / 1000;
LocalDateTime ldt = Instant.ofEpochMilli(timeMillis).atZone(ZoneId.systemDefault()).toLocalDateTime();
Run Code Online (Sandbox Code Playgroud)

为了查询服务,我们再次需要时间微秒,然后我们做

long timeMillis = dateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
long timeMicros = timeMillis * 1000;
Run Code Online (Sandbox Code Playgroud)

问题是我们没有取回时间微秒的精度。

是否可以创建具有微秒精度的 Instant ?
我们现在使用的是 Java 11。当我们的一个 JUnit 测试由于增加的微秒精度而失败时,我注意到了这一变化。

对于 JUnit 测试,我找到了一个解决方法:

private static final LocalDateTime START = LocalDateTime.now().truncatedTo(ChronoUnit.MILLIS);
Run Code Online (Sandbox Code Playgroud)


我不确定这是一种解决方法还是实际的解决方案,但添加时间戳的最后三微秒数字似乎有效。

System.currentTimeMillis  > 1565245051795    > 2019-08-08T06:17:31.795
Service.getTime           > 1565245051795306 > 2019-08-08T06:17:31.795306
Run Code Online (Sandbox Code Playgroud)

Ole*_*.V. 6

    long timeMicros = 1_565_245_051_795_306L;
    Instant i = Instant.EPOCH.plus(timeMicros, ChronoUnit.MICROS);
    System.out.println(i);
Run Code Online (Sandbox Code Playgroud)

输出是:

2019-08-08T06:17:31.795306Z

编辑:我更喜欢使用内置的微秒支持,而不是通过除法和乘法将微秒转换为毫秒和/或秒。此外,当明确地将它们添加到时代时感觉有点手持。

您已经知道如何转换InstantLocalDateTime,您已经在问题中展示了它,所以我不再重复。

编辑:

您是否有解决方案可以从 Instant 中恢复 timeMicros?

有几个选项。这样计算就不是那么复杂了,所以我可能会这样做:

    long microsBack = TimeUnit.SECONDS.toMicros(i.getEpochSecond())
            + TimeUnit.NANOSECONDS.toMicros(i.getNano());
    System.out.println(microsBack);
Run Code Online (Sandbox Code Playgroud)

1565245051795306

为了在第一次转换时更具风格,您可能更喜欢稍短的:

    long microsBack = ChronoUnit.MICROS.between(Instant.EPOCH, i);
Run Code Online (Sandbox Code Playgroud)

编辑:可能是吹毛求疵,但也是为了避免任何人的误解:LocalDateTime始终具有纳秒精度。只有该now方法在 Java 8 上具有毫秒精度。我在某处读到 Java 9 中的精度因平台而异,但您是对的,微秒精度似乎很典型。