How can I convert the result of System.nanoTime to a date in Java?

In the theory, you should not use the only System.nanotime(), but you can do a simple trick with this method in order to get nanoseconds of the current time.

public class TimeProvider{
    private final static long  jvm_diff;
    static {
        jvm_diff = System.currentTimeMillis()*1000_000-System.nanoTime();   
    }

    public static long getAccurateNow(){
        return System.nanoTime()+jvm_diff;

    }
}

Even though, you can create your own Clock implementation with this way for using high-level java data time classes.

public class HighLevelClock extends Clock {

    private final ZoneId zoneId;

    public HighLevelClock(ZoneId zoneId) {
        this.zoneId = zoneId;
    }
    static long nano_per_second = 1000_000_000L;

    @Override
    public ZoneId getZone() {
        return zoneId;
    }

    @Override
    public Clock withZone(ZoneId zoneId) {
        return new HighLevelClock(zoneId);
    }

    @Override
    public Instant instant() {
        long nanos = TimeProvider.getAccurateNow();
        return Instant.ofEpochSecond(nanos/nano_per_second, nanos%nano_per_second);
    }

}

Now we can use our clock implementation like the following:

Clock highLevelClock = new HighLevelClock(ZoneId.systemDefault());
System.out.println(LocalDateTime.now(highLevelClock));  //2020-04-04T19:22:06.756194290
System.out.println(ZonedDateTime.now(highLevelClock));  //2020-04-04T19:22:06.756202923+04:00[Asia/Baku]
System.out.println(LocalTime.now(highLevelClock));  //19:22:06.756220764

Unfortunately, System.nanoTime() is not what you want for this.

To quote the JavaDoc:

This method can only be used to measure elapsed time and is not related to any other notion of system or wall-clock time. The value returned represents nanoseconds since some fixed but arbitrary origin time (perhaps in the future, so values may be negative). The same origin is used by all invocations of this method in an instance of a Java virtual machine; other virtual machine instances are likely to use a different origin.

You probably want System.currentTimeMillis(), in which case you can use new Date(System.currentTimeMillis() + milliseconds) to get the date for that number of milliseconds in the future.

While you could then subtract System.nanoTime(), scale the value, and add System.currentTimeMillis() to have a similar result... since you're adding System.nanoTime() anyway and therefore have the original number of seconds, you could just use System.currentTimeMillis() directly.