Java 8 Instant.now() with nanosecond resolution?

Viewed 54946

Java 8's java.time.Instant stores in "nanosecond resolution", but using Instant.now() only provides millisecond resolution...

Instant instant = Instant.now();
System.out.println(instant);
System.out.println(instant.getNano());

Result...

2013-12-19T18:22:39.639Z
639000000

How can I get an Instant whose value is 'now', but with nanosecond resolution?

5 Answers

I needed a high-precision timer common to multiple JVM Instances.

As the Javadoc for System.nanoTime() explicitly states that each JVM is likely to use a different origin for this value, I created the following Test Class which calculates a Nanosecond offset to the Epoch so I can get a Timestamp with the precision of System.nanoTime() but a common origin. (That's basically the same idea proposed in the NanoClock solution posted by @logtwo)

Maybe it helps to visualise the differences in resolution between the values returned by Instant.now() & System.nanoTime() although both nominally have nanosecond precision.

On the Hardware I'm using this may cause deltas of about 1 Millisecond for the origin between JVM's, but that was more than adequate for my purposes.

import java.time.*;
import java.util.concurrent.TimeUnit;

public class EpochNanotimeOffset {

    private static final long NANO_TIME_EPOCH_OFFSET;
    /**/    static {
        final long     systemNanoTime         = System.nanoTime();
        final Instant  now                    = Clock.systemUTC().instant();
        final long     instantNanosSinceEpoch = Duration.between(Instant.EPOCH, now).toNanos();

        NANO_TIME_EPOCH_OFFSET = systemNanoTime - instantNanosSinceEpoch;
    }

    public static void main(final String[] args) throws InterruptedException {
        for (int i=0; i < 99; i++) {

            final long    systemNanoTime          = System.nanoTime();
            final Instant instant                 = Clock.systemUTC().instant();
            final long    instantNanos            = Duration.between(Instant.EPOCH, instant).toNanos();
            final long    correctedSystemNanoTime = systemNanoTime - NANO_TIME_EPOCH_OFFSET;
            final long    deltaNanos              = instantNanos   - correctedSystemNanoTime;

            Duration.between(Instant.EPOCH, instant).toNanos();

            System.out.print  (                  "OffsetNS=" + NANO_TIME_EPOCH_OFFSET );
            System.out.print  ('\t' + "instantNSsinceEpoch=" + instantNanos );
            System.out.print  ('\t' +   "correctedSystemNS=" + correctedSystemNanoTime );
            System.out.print  ('\t' +            "systemNS=" + systemNanoTime );
            System.out.println('\t' +             "deltaNS=" + deltaNanos );

//          TimeUnit.SECONDS.sleep(3);
        }
    }
}
Related