为什么新的 Java 8 日期时间 API 没有纳秒级精度?

2022-08-31 13:08:38

Java 8中新的日期时间API的功能之一应该是纳秒精度。但是,当我像这样将当前日期时间打印到控制台时

DateTimeFormatter formatter = DateTimeFormatter
    .ofPattern("yyyy-MM-dd'T'HH:mm:ss,nnnnnnnnnZ");
System.out.println(OffsetDateTime.now().format(formatter)); 

我只看到毫秒级精度:2015-11-02T12:33:26,746000000+0100

操作系统似乎确实支持纳秒精度。当我通过终端打印当前日期时间时

date -Ins

我看到2015-11-02T12:33:26,746134417 + 0100

如何在Java中获得纳秒精度?我在 Ubuntu 14.04 64 位上运行 Oracle Java 1.8.0_66


答案 1

通常,API确实具有纳秒级精度。例如:java.time

DateTimeFormatter formatter = DateTimeFormatter
    .ofPattern("yyyy-MM-dd'T'HH:mm:ss,nnnnnnnnnZ");
OffsetDateTime odt = OffsetDateTime.of(2015, 11, 2, 12, 38, 0, 123456789, ZoneOffset.UTC);
System.out.println(odt.format(formatter));

输出:

2015-11-02T12:38:00,123456789+0000

但是,它是返回的时钟值,它返回的值只有毫秒。OffsetDateTime.now()

从 Java 8 中的时钟实现:

此处提供的时钟实现基于 。这种方法几乎不能保证时钟的准确性。需要更精确时钟的应用程序必须使用不同的外部时钟(如 NTP 服务器)自己实现此抽象类。System.currentTimeMillis()

因此,这里没有什么固有的不精确之处 - 只是使用的默认实现。您可以创建自己的更精确的子类。但是,您应该注意,在不增加更多准确性的情况下添加更多精度可能不是很有用。(不可否认,有时可能是这样...)ClockSystem.currentTimeMillis()


答案 2

为了对Jon Skeet的答案进行重要的补充,Java 9应该以更高的精度提供时钟 - 请参阅错误日志。背景:在许多操作系统(尤其是Linux)上,有更好的时钟可用。

Java.time.Clock 的 Java SE 8 规范指出,“系统工厂方法提供基于最佳可用
系统时钟的时钟。这可能使用System.currentTimeMillis(),或者更高分辨率的时钟(如果有的话)。在 JDK 8 中,返回的时钟的实现
基于 System.currentTimeMillis(),因此只有一毫秒的分辨率。在 JDK 9 中,实现
基于 System.currentTimeMillis() 正在使用的底层本机时钟,提供该时钟提供的最大分辨率。在大多数系统上,这可能是微秒,有时甚至是十分之一微秒。

假设这些系统工厂方法返回的时钟将始终具有毫秒精度并主动依赖于它的应用程序,因此可能需要更新以考虑更高分辨率的可能性,如API文档中
所述。

还应该注意的是一个(奇特的)事实,即第二精度在闰秒附近不会存在 - 即使在Java 9中也不会。


推荐