如何将 System.nanoTime 的结果转换为 Java 中的日期?

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

我想将 System.nanoTime() 的结果转换为日期。

public void tempBan(Player p, Player banner, int timeInSeconds){
    Long timeInNano = (long) (timeInSeconds * 10^9);
    int newTime = (int) (System.nanoTime() + timeInNano);
    // here I want to convert newTime to a date 
}

我通过乘以 10^9 将秒数转换为 nanoseconds。现在我需要将当前系统时间加上我转换成纳秒的参数转换成日期。

不幸的是,System.nanoTime() 不是您想要的。

引用 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.

您可能需要 System.currentTimeMillis(),在这种情况下,您可以使用 new Date(System.currentTimeMillis() + milliseconds) 获取未来该毫秒数的日期。

虽然您随后可以减去 System.nanoTime()、缩放该值并添加 System.currentTimeMillis() 以获得类似的结果...因为您无论如何都要添加 System.nanoTime(),因此具有原来的秒数,直接用System.currentTimeMillis()即可。

您可以使用以下代码将其转换为系统时间

public static long convertToUnixMs(final long timeMs) {
    final long refMonoMs = monoTimeMs();
    final long refUnixMx = System.currentTimeMillis();

    return refUnixMx + (timeMs - refMonoMs);
}
public static long monoTimeMs() {
        return System.nanoTime() / 1000000;
    }

解释:

System.nonoTime() 是一个只增加的单调时间,它不知道现在几点,但无论如何它只会增加。因此,这是测量流逝时间的好方法。但是你不能把它转换成一个合理的时间,因为它没有参考当前时间。

提供的方法是一种将您存储的纳秒时间转换为合理时间的方法。首先,您有一个 timeMs,它是您想要转换的纳秒时间。然后,您创建了另一个 nanotime(即 refMonoMs)和另一个 System.currentTimeMillis()(即 refUnixMx)。然后从 timeMs 中减去 refMonoMs,然后将引用添加回其中以获得合理的时间。

理论上,你不应该只使用System.nanotime(),但你可以用这个方法做一个简单的技巧来获得当前时间的纳秒。

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;

    }
}

尽管如此,您可以使用这种方式创建自己的时钟实现,以使用高级 java 数据时间 类。

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);
    }

}

现在我们可以像下面这样使用我们的时钟实现:

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