В системе Unix есть ли способ получить метку времени с точностью до микросекунд в Java? Что-то вроде gettimeofday
функции C.
Текущее время в микросекундах в java
Ответы (11)
Нет, у Java такой возможности нет.
У него есть System.nanoTime (), но он просто дает смещение от некоторого ранее известного времени. Таким образом, хотя вы не можете извлечь из этого абсолютное число, вы можете использовать его для измерения наносекундной (или более высокой) точности.
Обратите внимание, что в JavaDoc говорится, что, хотя это обеспечивает точность в наносекунду, это не означает точность в наносекунду. Итак, возьмите какой-нибудь достаточно большой модуль возвращаемого значения.
Clock
, который позволяет запечатлеть текущий момент с разрешением меньше миллисекунд. На MacBook Pro Retina я получаю текущее время в микросекундах (шесть цифр десятичной дроби). Фактические результаты и точность зависят от основного тактового оборудования главного компьютера.
- person Basil Bourque; 08.11.2017
tl;dr
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
На практике вы увидите только микросекунды, захваченные с помощью .now
, поскольку современные обычные компьютерные аппаратные часы не точны в наносекундах.
Подробности
Другие ответы несколько устарели с 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. И лучше, чем микросекунды, указанные в Вопросе.
Clock
Реализация
Хотя классы java.time поддерживают данные, представляющие значения в наносекундах, классы еще не генерируют значения в наносекундах. В методах now()
используется та же старая реализация часов, что и в старых классах даты и времени, _ 6_. У нас есть новый интерфейс 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 зависит от часов базового компьютерного оборудования, чтобы узнать текущий момент.
- Разрешение аппаратных часов сильно различается. Например, если аппаратные часы конкретного компьютера поддерживают детализацию только микросекунд, любые сгенерированные значения даты и времени будут имеют только шесть цифр дробной секунды, причем последние три цифры нули.
- Точность аппаратных часов сильно различается. Просто потому, что часы генерируют значение с несколькими цифрами десятичной доли секунды, эти цифры могут быть неточными, просто приблизительными, дрейфующими от фактического времени, как можно было бы прочитать из атомные часы. Другими словами, то, что вы видите группу цифр справа от десятичного знака, не означает, что вы можете быть уверены, что время, прошедшее между такими показаниями, будет верным до этой минутной степени.
Clock
. Даже в этом случае в Java 8 классы java.time полезны для хранения значений, полученных из других источников, таких как микросекунды, в базе данных Postgres. Но будьте осторожны с неточностью значений в диапазоне микросекунд и наносекунд; обычное компьютерное оборудование может не обеспечивать точное отслеживание времени аппаратных часов. Значение с шестью или девятью цифрами дробной секунды может быть неверным.
- person Basil Bourque; 20.09.2016
Вы можете использовать System.nanoTime()
:
long start = System.nanoTime();
// do stuff
long end = System.nanoTime();
long microseconds = (end - start) / 1000;
чтобы получить время в наносекундах, но это строго относительная мера. Это не имеет абсолютного значения. Это полезно только для сравнения с другими нано временами, чтобы измерить, сколько времени что-то потребовалось.
Как уже указывалось на других плакатах; ваши системные часы, вероятно, не синхронизированы с текущим мировым временем с точностью до микросекунд. Тем не менее, это временные метки с точностью до микросекунд, которые можно использовать как гибрид как для индикации текущего времени на стене, так и для измерения / профилирования продолжительности событий.
Я помечаю все события / сообщения, записанные в файлы журнала, с помощью временных меток, например «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) ;
}
}
MicroTimestamp.INSTANCE.get()
могут быть проблематичными.
- person Ahmed; 07.10.2014
get()
нет ничего, что обновляло бы переменные-члены; он использует только временные локальные переменные.
- person Jason Smith; 23.04.2020
Возможно, вы могли бы создать компонент, который определяет смещение между 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
...
Используйте Instant для вычисления микросекунд с момента Epoch:
val instant = Instant.now();
val currentTimeMicros = instant.getEpochSecond() * 1000_000 + instant.getNano() / 1000;
Если вас интересует Linux: если вы извлечете исходный код для «currentTimeMillis ()», вы увидите, что в Linux, если вы вызовете этот метод, он вернется на микросекунду назад. Однако Java затем усекает микросекунды и возвращает вам миллисекунды. Отчасти это связано с тем, что Java должна быть кроссплатформенной, поэтому предоставление методов специально для Linux было большим запретом в те времена (помните, что грубая поддержка софт-ссылок начиная с версии 1.6 назад ?!). Это еще и потому, что, хотя часы могут возвращать вам микросекунды в Linux, это не обязательно означает, что они подходят для проверки времени. На уровне микросекунд вам необходимо знать, что NTP не корректирует ваше время и что ваши часы не слишком сильно отклоняются во время вызовов методов.
Это означает, что теоретически в Linux вы можете написать оболочку JNI, такую же, как в пакете System, но не усекать микросекунды.
«быстрое и грязное» решение, которое я в итоге выбрал:
TimeUnit.NANOSECONDS.toMicros(System.nanoTime());
ОБНОВИТЬ:
Первоначально я выбрал System.nanoTime, но затем я обнаружил, что его следует использовать только в течение прошедшего времени, в конечном итоге я изменил свой код, чтобы он работал с миллисекундами или в некоторых местах использовал:
TimeUnit.MILLISECONDS.toMicros(System.currentTimeMillis());
но это просто добавит нули в конце значения (микрос = миллис * 1000)
Оставил этот ответ здесь как «предупреждающий знак» на случай, если кто-то еще подумает о nanoTime :)
System.nanoTime
для времени настенных часов: «Этот метод может использоваться только для измерения прошедшего времени и не связан с каким-либо другим понятием системного времени или времени настенных часов».
- person Basil Bourque; 03.11.2015
Java поддерживает микросекунды через TimeUnit
enum.
Вот документ java: Enum TimeUnit
Вы можете получить микросекунды в java следующим образом:
long microsenconds = TimeUnit.MILLISECONDS.toMicros(System.currentTimeMillis());
Вы также можете преобразовать микросекунды обратно в другие единицы времени, например:
long seconds = TimeUnit.MICROSECONDS.toSeconds(microsenconds);
Если вы собираетесь использовать его для системы реального времени, возможно, 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();
Вот пример того, как создать текущую метку времени UnsignedLong:
UnsignedLong current = new UnsignedLong(new Timestamp(new Date().getTime()).getTime());
Instant.now()
- person Basil Bourque   schedule 08.11.2017val instant = Instant.now();
val currentTimeMicros = instant.getEpochSecond() * 1000_000 + instant.getNano() / 1000;
- person Michael M.   schedule 25.04.2019