Текущее время в микросекундах в Яве - PullRequest
97 голосов
/ 11 ноября 2009

В системе Unix, есть ли способ получить метку времени с точностью до микросекундного уровня в Java? Что-то вроде функции C gettimeofday.

Ответы [ 11 ]

139 голосов
/ 11 ноября 2009

Нет, у Java нет такой возможности.

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

Обратите внимание, что JavaDoc говорит, что, хотя это обеспечивает точность наносекунд, это не означает точность наносекунд. Итак, возьмите достаточно большой модуль возвращаемого значения.

62 голосов
/ 05 февраля 2016

ТЛ; др

Java 9 и более поздние версии: разрешение до наносекунд при захвате текущего момента. Это 9 цифр десятичной дроби.

Instant.now()   

2017-12-23T12: 34: 56.123456789Z

Для ограничения до микросекунд , усечение.

Instant                // Represent a moment in UTC. 
.now()                 // Capture the current moment. Returns a `Instant` object. 
.truncatedTo(          // Lop off the finer part of this moment. 
    ChronoUnit.MICROS  // Granularity to which we are truncating. 
)                      // Returns another `Instant` object rather than changing the original, per the immutable objects pattern. 

2017-12-23T12: 34: 56.123456Z

Подробнее

Остальные ответы несколько устарели с Java 8.

java.time

Java 8 и более поздние версии поставляются с java.time framework. Эти новые классы вытесняют дефектные и проблемные классы даты и времени, поставляемые с самыми ранними версиями Java, такими как java.util.Date/.Calendar и java.text.SimpleDateFormat. Каркас определен JSR 310, вдохновленный Joda-Time , расширенным проектом ThreeTen-Extra.

Классы в java.time разрешают до наносекунд , что намного меньше, чем миллисекунд , используемых как старыми классами даты и времени, так и Joda-Time. И тоньше, чем микросекунд , заданных в Вопросе.

enter image description here

Clock Реализация

Хотя классы java.time поддерживают данные, представляющие значения в наносекундах, классы еще не генерируют значения в наносекундах. Методы now() используют ту же старую реализацию часов, что и старые классы даты и времени, System.currentTimeMillis(). У нас есть новый Clock интерфейс в java.time, но реализация для этого интерфейса - те же самые старые часы миллисекунд.

Таким образом, вы можете отформатировать текстовое представление результата ZonedDateTime.now( ZoneId.of( "America/Montreal" ) ), чтобы увидеть девять цифр доли секунды, но только первые три цифры будут иметь такие цифры:

2017-12-23T12:34:56.789000000Z

Новые часы в Java 9

Реализации Java 9 в OpenJDK и Oracle имеют новую реализацию по умолчанию Clock с более высокой степенью детализации, вплоть до полной наносекундной возможности классов java.time.

См. Проблему OpenJDK, Повышение точности реализации java.time.Clock.systemUTC () . Эта проблема была успешно решена.

2017-12-23T12:34:56.123456789Z

На MacBook Pro (Retina, 15-дюймовый, конец 2013 г.) с macOS Sierra я получаю текущий момент в микросекундах (до шести цифр десятичной дроби).

2017-12-23T12:34:56.123456Z

Аппаратные часы

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

  • Разрешение аппаратных часов сильно различается. Например, если аппаратные часы конкретного компьютера поддерживают только микросекунды гранулярность, любые сгенерированные значения даты и времени будут иметь только шесть цифр доли секунды с последними тремя цифрами, являющимися нулями.
  • Точность аппаратных часов сильно различается. Просто потому, что часы генерируют значение с несколькими цифрами десятичной доли секунды, эти цифры могут быть неточными, только приблизительными, отклоненными от фактического времени, как это может быть считано с атомных часов . Другими словами, то, что вы видите группу цифр справа от десятичной отметки, не означает, что вы можете доверять истекшему времени между такими показаниями, чтобы оно соответствовало этой минутной степени.
54 голосов
/ 11 ноября 2009

Вы можете использовать System.nanoTime():

long start = System.nanoTime();
// do stuff
long end = System.nanoTime();
long microseconds = (end - start) / 1000;

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

14 голосов
/ 22 октября 2012

Как уже указано на других плакатах; Ваши системные часы, вероятно, не синхронизированы с микросекундами с реальным мировым временем. Тем не менее, метки времени с микросекундной точностью полезны как гибрид для отображения текущего времени стены и измерения / профилирования длительности событий.

Я отмечаю все события / сообщения, записанные в файлы журнала, используя временные метки, такие как «2012-10-21 19: 13: 45.267128». Они передают как , когда это произошло (время "стены"), и также могут использоваться для измерения продолжительности между этим и следующим событием в файле журнала (относительная разница в микросекундах) .

Для этого вам нужно связать System.currentTimeMillis () с System.nanoTime () и работать с System.nanoTime () с этого момента. Пример кода:

/**
 * Class to generate timestamps with microsecond precision
 * For example: MicroTimestamp.INSTANCE.get() = "2012-10-21 19:13:45.267128"
 */ 
public enum MicroTimestamp 
{  INSTANCE ;

   private long              startDate ;
   private long              startNanoseconds ;
   private SimpleDateFormat  dateFormat ;

   private MicroTimestamp()
   {  this.startDate = System.currentTimeMillis() ;
      this.startNanoseconds = System.nanoTime() ;
      this.dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS") ;
   }

   public String get()
   {  long microSeconds = (System.nanoTime() - this.startNanoseconds) / 1000 ;
      long date = this.startDate + (microSeconds/1000) ;
      return this.dateFormat.format(date) + String.format("%03d", microSeconds % 1000) ;
   }
}
2 голосов
/ 18 мая 2017

Вы можете создать компонент, который определяет смещение между System.nanoTime () и System.currentTimeMillis () и эффективно получать наносекунды с начала эпохи.

public class TimerImpl implements Timer {

    private final long offset;

    private static long calculateOffset() {
        final long nano = System.nanoTime();
        final long nanoFromMilli = System.currentTimeMillis() * 1_000_000;
        return nanoFromMilli - nano;
    }

    public TimerImpl() {
        final int count = 500;
        BigDecimal offsetSum = BigDecimal.ZERO;
        for (int i = 0; i < count; i++) {
            offsetSum = offsetSum.add(BigDecimal.valueOf(calculateOffset()));
        }
        offset = (offsetSum.divide(BigDecimal.valueOf(count))).longValue();
    }

    public long nowNano() {
        return offset + System.nanoTime();
    }

    public long nowMicro() {
        return (offset + System.nanoTime()) / 1000;
    }

    public long nowMilli() {
        return System.currentTimeMillis();
    }
}

Следующий тест дает довольно хорошие результаты на моей машине.

    final Timer timer = new TimerImpl();
    while (true) {
        System.out.println(timer.nowNano());
        System.out.println(timer.nowMilli());
    }

Разница, кажется, колеблется в диапазоне + -3 мс. Я полагаю, можно немного больше изменить расчет смещения.

1495065607202174413
1495065607203
1495065607202177574
1495065607203
...
1495065607372205730
1495065607370
1495065607372208890
1495065607370
...
2 голосов
/ 21 сентября 2016

Java поддерживает микросекунды до TimeUnit enum.

Вот документация Java: Enum TimeUnit

Вы можете получить микросекунды в Java следующим образом:

long microsenconds = TimeUnit.MILLISECONDS.toMicros(System.currentTimeMillis());

Вы также можете преобразовать микросекунды в другие единицы времени, например:

long seconds = TimeUnit.MICROSECONDS.toSeconds(microsenconds);
2 голосов
/ 14 октября 2015

«быстрое и грязное» решение, с которым я в конце концов пошел:

TimeUnit.NANOSECONDS.toMicros(System.nanoTime());

UPDATE:

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

TimeUnit.MILLISECONDS.toMicros(System.currentTimeMillis());

но это просто добавит нули в конце значения (micros = millis * 1000)

Оставьте этот ответ здесь как "предупреждающий знак" на случай, если кто-то еще подумает о nanoTime:)

2 голосов
/ 31 декабря 2014

Если вы заинтересованы в Linux: Если вы выберете исходный код для currentTimeMillis (), вы увидите, что в Linux, если вы вызовете этот метод, он вернется на микросекунду назад. Однако Java затем обрезает микросекунды и возвращает вам миллисекунды. Отчасти это связано с тем, что Java должна быть кроссплатформенной, поэтому предоставление методов, специально предназначенных для Linux, было очень сложным делом (помните, что грубая поддержка софт-линков от 1.6 назад ?!). Это также потому, что, хотя ваши часы могут возвращать вам микросекунды в Linux, это не обязательно означает, что это будет хорошо для проверки времени. На микросекундных уровнях вы должны знать, что NTP не перераспределяет ваше время и что ваши часы не слишком сильно сдвигаются во время вызовов методов.

Это означает, что теоретически в Linux вы можете написать оболочку JNI, такую ​​же, как в пакете System, но не обрезать микросекунды.

0 голосов
/ 25 апреля 2019

Используйте Instant для вычисления микросекунд с начала эпохи:

val instant = Instant.now();
val currentTimeMicros = instant.getEpochSecond() * 1000_000 + instant.getNano() / 1000;
0 голосов
/ 27 октября 2014

Если вы намереваетесь использовать его для системы реального времени, возможно, java не лучший выбор для получения метки времени. Но если вы собираетесь использовать if для уникального ключа, то ответа Джейсона Смита будет достаточно. Но на всякий случай, чтобы ожидать, что 2 элемента получат одну и ту же временную метку (это возможно, если эти 2 были обработаны почти одновременно), вы можете выполнить цикл, пока последняя временная метка не будет равна текущей временной метке.

String timestamp = new String();
do {
    timestamp = String.valueOf(MicroTimestamp.INSTANCE.get());
    item.setTimestamp(timestamp);
} while(lasttimestamp.equals(timestamp));
lasttimestamp = item.getTimestamp();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...