为什么新的Java 8 Date Time API没有纳秒精度?

Tho*_*ich 72 java java-8 java-time

Java 8中新的Date Time API的一个特性应该是纳秒精度.但是,当我将当前日期时间打印到控制台时,就像这样

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

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

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

date -Ins
Run Code Online (Sandbox Code Playgroud)

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

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

Jon*_*eet 106

java.time一般的API 确实有纳秒的精度.例如:

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));
Run Code Online (Sandbox Code Playgroud)

输出:

2015-11-02T12:38:00,123456789+0000
Run Code Online (Sandbox Code Playgroud)

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

ClockJava 8中的实现:

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

所以这里没有什么本质上不精确的 - 只是默认的Clock使用实现System.currentTimeMillis().您可以创建自己更精确的子类.但是,您应该注意,在不增加更多精度的情况下添加更多精度可能并不十分有用.(有时它可能是,不可否认......)

  • 最后一点特别重要.[`nanosleep(2)`](http://linux.die.net/man/2/nanosleep)在标准的消费级硬件上也有类似的问题,因为睡眠精确的纳秒数需要大约1的误差CPU周期,在先发制人的多任务环境中无法真正完成.如果您只需要相对于彼此订购各种事件而不关心它们之间的精确间隔,那么高精度可能是有用的.我假设时钟是单调增加的,我希望*是真的. (8认同)

Men*_*ild 56

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

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

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

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

  • @Thunderforge像`ChronoUnit.SECONDS.between(instant1,instant2)`这样的表达式永远无法计算闰秒.`java.time`-设计师决定隐藏闰秒并假装每分钟包含60秒.他们的规范正式授权UTC-SLS,JDK中的实际实现事实上就像POSIX不像UTC-SLS - 只是忽略了闰秒.所有已知的OS时钟(作为`Clock.systemUTC()`的基础表现相同或应用某种时钟复位或闰秒涂抹.SI-secs没有建模.如果你认真寻找真正的闰秒支持,那么考虑我的lib Time4J. (6认同)