如何在Java8中使用DateAPI实现精确的纳秒精度

如何在Java8中使用DateAPI实现精确的纳秒精度,java,java-8,java-time,Java,Java 8,Java Time,我们正试图获得精确的纳秒和9个精确值来捕获时间 使用Java8我们可以实现如下所述 @Test public void testNanoClock() throws InterruptedException{ DateTimeFormatter formatter = new DateTimeFormatterBuilder() .appendInstant(9).toFormatter(); for (int i=0; i<10; i++) {

我们正试图获得精确的纳秒和9个精确值来捕获时间

使用Java8我们可以实现如下所述

@Test
public void testNanoClock() throws InterruptedException{
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
              .appendInstant(9).toFormatter();
       for (int i=0; i<10; i++) {
       final Clock clock = new NanoClock();
       log.info(formatter.format(clock.instant()));
       Thread.sleep(200);
       }
}
下面给出了该类的完整实现

public class NanoClock extends Clock {

    private final Clock clock;

    private final long initialNanos;

    private final Instant initialInstant;

    public NanoClock() {
        this(Clock.systemUTC());
    }

    public NanoClock(final Clock clock) {
        this.clock = clock;
        initialInstant = clock.instant();
        initialNanos = getSystemNanos();
    }

    @Override
    public ZoneId getZone() {
        return clock.getZone();
    }

    @Override
    public Clock withZone(ZoneId zone) {
        return new NanoClock(clock.withZone(zone));
    }

    @Override
    public Instant instant() {
        return initialInstant.plusNanos(getSystemNanos() - initialNanos);
    }

    private long getSystemNanos() {
        return System.nanoTime();
    }
}
通过使用上述代码,我们能够获得纳秒级的时间以及9个精度值:

2017-10-08T16:45:45.232000378Z

但在这种情况下,微秒是0(零)


我们如何在没有0的情况下实现精确的纳秒时间和9个精度值?它是如何工作的?

您的代码在循环中创建了一个新的
纳米时钟实例。这会每次重置
initialInstant
initialNanos
,因此您永远看不到nanos的效果。要使这一切工作,您需要将时钟移出循环,可能是一个静态常数


您还应该注意,随着时间的推移,此时钟可能会偏离实时,因为
System.currentTimeMillis()
System.nanoTime()
来自操作系统中的不同时钟源,用于不同的目的(前者是日历日期/墙时间,后者是经过的时间)。因此,您实际上是在测量自时钟创建以来经过的时间(在一天的过程中,两者之间可能存在一些偏差)。

顺便说一句,Java 9有一个新的
clock
实现,它以纳秒的分辨率捕获当前时刻。您可能希望在OpenJDK中查看其源代码。请记住,据我所知,主流计算硬件没有配备足够灵敏的时钟来准确记录纳秒。谢谢Stephen的回复。我计划将这段代码放到一个生产环境中的应用服务器中,以捕获纳秒级的一些事件。您是否建议将时钟初始化移到for循环之外会得到正确的结果?或者你有什么其他建议可以用纳秒来记录时间吗?@YerriswamyManchi在回答中说,
System.nanoTime()
与当前时间无关。选中:“此方法只能用于测量经过的时间,与系统或挂钟时间的任何其他概念无关。”无论如何,在Java8中,
clock
类的精度限制为毫秒。在Java9中,它正在使用,但只有在系统中可用时才使用
public class NanoClock extends Clock {

    private final Clock clock;

    private final long initialNanos;

    private final Instant initialInstant;

    public NanoClock() {
        this(Clock.systemUTC());
    }

    public NanoClock(final Clock clock) {
        this.clock = clock;
        initialInstant = clock.instant();
        initialNanos = getSystemNanos();
    }

    @Override
    public ZoneId getZone() {
        return clock.getZone();
    }

    @Override
    public Clock withZone(ZoneId zone) {
        return new NanoClock(clock.withZone(zone));
    }

    @Override
    public Instant instant() {
        return initialInstant.plusNanos(getSystemNanos() - initialNanos);
    }

    private long getSystemNanos() {
        return System.nanoTime();
    }
}