Java 8 Instant.now() с разрешением наносекунды?

Java 8 java.time.Instant хранит в "наносекундном разрешении", но использование Instant.now() обеспечивает только миллисекундное разрешение...

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

Результат...

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

Как я могу получить Instant, значение которого теперь, но с разрешением наносекунд?

Ответ 1

В то время как по умолчанию часы Java8 не обеспечивают разрешение в наносекундах, вы можете комбинировать его с возможностью Java измерять разницу во времени с разрешением наносекунд, создавая тем самым фактические часы с поддержкой наносекунд.

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 Instant instant()
    {
        return initialInstant.plusNanos(getSystemNanos() - initialNanos);
    }

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

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

Использование этого просто: просто добавьте дополнительный параметр в Instant.now() или вызовите Clock.instant() напрямую:

    final Clock clock = new NanoClock();   
    final Instant instant = Instant.now(clock);
    System.out.println(instant);
    System.out.println(instant.getNano());

Хотя это решение может работать, даже если вы каждый раз заново создаете экземпляры NanoClock, всегда лучше придерживаться сохраненных часов, инициализированных в начале вашего кода, а затем использовать там, где это необходимо.

Ответ 2

Вы можете считать себя счастливым, если вы получите даже миллисекундное разрешение.

Instant может моделировать время до наносекундной точности, но реальное оборудование на вашем компьютере, которое отслеживает время настенных часов, обычно имеет разрешение около 10 мс, а точность почти наверняка будет немного ниже (100 мс будет оптимистическое предположение).

Сравните это с System.nanoTime(), который дает разрешение в микросекундах, но не дает абсолютного времени настенных часов. Понятно, что уже есть компромисс в работе, чтобы дать вам такое разрешение, но на три порядка меньше наносекунд.

Ответ 3

Вы можете получить мгновенный доступ с помощью "наносекунд", используя еще один более точный java.time.Clock с помощью Instant-метода public static Instant now(Clock clock). В вашем примере часы по умолчанию обычно используют System.currentTimeMillis(), которые не могут отображать любые наносекунды.

Помните, что в наносекундном разрешении (в реальном времени) нет часов. Внутреннее средство представления наносекунд java.time.Instant в основном связано с требованием сопоставлять временные метки базы данных, данные в наносекундной точности (но обычно неточно наносекунды!).

Обновление с 2015-12-29: Java-9 обеспечит лучшие часы, см. мой новый пост.

Ответ 4

Итак, я потратил некоторое время на изучение Javadoc здесь:

http://download.java.net/jdk8/docs/api/java/time/Instant.html

Похоже, вы должны сделать следующее:

Instant inst = Instant.now();
long time = inst.getEpochSecond();
time *= 1000000000l; //convert to nanoseconds
time += inst.getNano(); //the nanoseconds returned by inst.getNano() are the nanoseconds past the second so they need to be added to the epoch second

Тем не менее, другие ответчики делают хороший вывод о том, что очень сложно получить точный нано-второй раз, поскольку компьютеры обычно не имеют возможности отслеживать время до этого разрешения.