Как измерить время, прошедшее в Java? [дубликат]
этот вопрос уже есть ответ здесь:
- как определить время выполнения метода на Java? 36 ответов
- как вычислить прошедшее время события в java? [дубликат] 6 ответов
Я хочу иметь что-то вроде этого:
public class Stream
{
public startTime;
public endTime;
public getDuration()
{
return startTime - endTime;
}
}
также важно, чтобы, например, если startTime это 23:00 и endTime 1:00, чтобы получить Продолжительность 2:00.
какие типы использовать для выполнения этого в Java?
15 ответов
к сожалению, ни один из десяти ответов, опубликованных до сих пор, не совсем прав.
если вы измеряете прошедшее время, и вы хотите, чтобы это было правильно, вы должны использовать System.nanoTime()
. Вы не можете использовать System.currentTimeMillis()
, Если вы не возражаете, что ваш результат неправильный.
цель nanoTime
измерения истек время и цель currentTimeMillis
- измерить настенные часы времени. Нельзя использовать для других целей. Причина разве что часы компьютера не идеальны; они всегда дрейфуют и иногда нуждаются в корректировке. Эта коррекция может произойти либо вручную, либо в случае большинства машин, есть процесс, который работает и постоянно выдает небольшие поправки к системным часам ("настенные часы"). Они, как правило, случаются часто. Еще одна такая коррекция происходит всякий раз, когда есть скачкообразная секунда.
С nanoTime
цель состоит в том, чтобы измерить прошедшее время, на него не влияет ни одна из этих небольших поправок. Это то, что вы хотите использовать. Любые тайминги в настоящее время ведутся с currentTimeMillis
будет-возможно даже негативное.
вы можете сказать: "это не похоже на то, что это когда-нибудь действительно будет иметь значение", на что я говорю, может быть, нет, но в целом, не правильный код просто лучше, чем неправильный код? Кроме того, nanoTime
короче для ввода в любом случае.
ранее опубликованные отказы от ответственности о nanoTime
обычно иметь только точность микросекунд действительны. Также это может занять больше, чем целая микросекунда для вызова, в зависимости от обстоятельств (как и другой), поэтому не ожидайте, что очень маленькие интервалы времени будут правильно.
какие типы использовать для выполнения этого в Java?
короткий ответ:long
. Теперь подробнее о том, как измерить...
новый класс:
public class TimeWatch {
long starts;
public static TimeWatch start() {
return new TimeWatch();
}
private TimeWatch() {
reset();
}
public TimeWatch reset() {
starts = System.currentTimeMillis();
return this;
}
public long time() {
long ends = System.currentTimeMillis();
return ends - starts;
}
public long time(TimeUnit unit) {
return unit.convert(time(), TimeUnit.MILLISECONDS);
}
}
использование:
TimeWatch watch = TimeWatch.start();
// do something
long passedTimeInMs = watch.time();
long passedTimeInSeconds = watch.time(TimeUnit.SECONDS);
после этого прошедшее время может быть преобразовано в любой формат, который вам нравится, с календарем, например
Greetz, Гхад!--3-->
Если цель состоит в том, чтобы просто распечатать грубую информацию о времени в журналах программ, то простое решение для проектов Java - это не писать свои собственные классы секундомера или таймера, а просто использовать org.apache.commons.lang.time.StopWatch
класс, который является частью Apache Commons Lang.
final StopWatch stopwatch = new StopWatch();
stopwatch.start();
LOGGER.debug("Starting long calculations: {}", stopwatch);
...
LOGGER.debug("Time after key part of calcuation: {}", stopwatch);
...
LOGGER.debug("Finished calculating {}", stopwatch);
tl; dr
например, если startTime это 23:00 и endTime 1:00, чтобы получить Продолжительность 2: 00.
не возможно. Если у вас есть только время суток, часы останавливаются в полночь. Без контекста дат, как мы узнаем, если вы имеете в виду, что я на следующий день, на следующей неделе или в следующем десятилетии?
таким образом, переход с 11 вечера до 1 утра означает перемещение назад во времени 22 часа, работает стрелки часов против часовой стрелки. Видеть результат ниже отрицательный двадцать два часа.
Duration.between( // Represent a span of time a total number of seconds plus a fractional second in nanoseconds.
LocalTime.of( 23 , 0 ) , // A time-of-day without a date and without a time zone.
LocalTime.of( 1 , 0 ) // A time-of-day clock stops at midnight. So getting to 1 AM from 11 PM means going backwards 22 hours.
) // Return a `Duration` object.
.toString() // Generate a `String` representing this span of time using standard ISO 8601 format: PnYnMnDTnHnMnS
PT-22H
пересечение полуночи требует большего контекста даты в дополнение к времени суток (см. ниже).
как измерить время, прошедшее в Java?
- захват текущего момента в UTC, с
Instant.now()
. - захватить еще один такой момент позже.
- перейти как к
Duration.between
. - (a) из результирующего
Duration
объект, извлеките количество 24-часовых дней, часов, минут, секунд и дробной секунды в наносекундах, вызвав различныеto…Part
методы.
(b) или позвонитеtoString
для созданияString
на стандартный формат ISO 8601 ofPnYnMnDTnHnMnS
.
пример кода, используя пару Instant
объекты.
Duration.between( // Represent a span of time a total number of seconds plus a fractional second in nanoseconds.
then , // Some other `Instant` object, captured earlier with `Instant.now()`.
Instant.now() // Capture the current moment in UTC with a resolution as fine as nanoseconds, depending on the limits of your host computer hardware clock and operating system. Generally you will get current moment in microseconds (six decimal digits of fractional second) in Java 9, 10, and 11, but only milliseconds in Java 8.
) // Return a `Duration` object.
.toString() // Generate a `String` representing this span of time using standard ISO 8601 format: PnYnMnDTnHnMnS
PT3M27.602197S
Новая Технология В Java 8+
у нас есть новая технология для этого теперь встроена в Java 8 и позже,java.время основы.
java.время
java.временные рамки определяются JSR 310, вдохновленный очень успешным Joda-Time, продлен ThreeTen-Extra проект, и описано в Oracle Учебник.
старые классы даты и времени, такие как java.утиль.Дата./Календарь в комплекте с самыми ранними версиями Java оказался плохо спроектированным, запутанным и хлопотным. Они вытеснены java.классы время.
разрешение
другие ответы обсудить резолюцию.
java.время занятий есть НС разрешение, до девяти цифр десятичной доли секунды. Например, 2016-03-12T04:29:39.123456789Z
.
оба старые java.утиль.Дата./Классы календаря и классы времени Joda имеют разрешение миллисекунды (3 цифры дроби). Например, 2016-03-12T04:29:39.123Z
.
в Java 8 текущий момент извлекается с разрешением до миллисекунды только из-за устаревшей проблемы. В Java 9 и более поздних версиях текущее время может быть определено до разрешения наносекунды при условии, что аппаратные часы вашего компьютера работают так точно.
Времени
если вы действительно хотите работать только с временем суток без какой-либо даты или часового пояса, используйте LocalTime
класса.
LocalTime sooner = LocalTime.of ( 17, 00 );
LocalTime later = LocalTime.of ( 19, 00 );
A Duration
представляет промежуток времени, который он определяет как количество секунд плюс наносекунды.
Duration duration = Duration.between ( sooner, later );
дамп в консоли.
System.out.println ( "sooner: " + sooner + " | later: " + later + " | duration: " + duration );
раньше: 17: 00 / позже: 19: 00 | Продолжительность: PT2H
ISO 8601
обратите внимание на вывод по умолчанию Duration::toString
в стандарт ISO 8601. В этом формате P
отмечает начало (как в "период"), и T
отделяет любую часть лет-месяцев-дней от части часов-минут-секунд.
Пересечение Полночь
к сожалению, работа с временем суток только становится сложным, когда вы обернуть вокруг часов, пересекающих полночь. The LocalTime
класс обрабатывает это, предполагая, что вы хотите вернуться к более ранней точке дня.
используя тот же код, что и выше, но идя от 23:00
to 01:00
результат отрицательный двадцать два часа (PT-22H
).
LocalTime sooner = LocalTime.of ( 23, 0 );
LocalTime later = LocalTime.of ( 1, 0 );
раньше: 23: 00 / позже: 01: 00 | Продолжительность: PT-22H
Времени
если вы собираетесь пересечь полночь, вероятно, имеет смысл работать со значениями даты-времени, а не только со значениями времени суток.
Часовой Пояс
часовой пояс имеет решающее значение для даты. Итак, мы указываем три пункта: (1) желаемую дату, (2) желаемое время суток и (3) часовой пояс как контекст для интерпретации этой даты и времени. Здесь мы произвольно выбираем часовой пояс Монреаль зона.
если вы определяете дату только смещение-от-UTC используйте ZoneOffset
с OffsetDateTime
. Если у вас есть полный часовой пояс (смещение плюс правила для обработки аномалий, таких как летнее время Time), используйте ZoneId
с ZonedDateTime
.
LocalDate localDate = LocalDate.of ( 2016, 1, 23 );
ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime sooner = ZonedDateTime.of ( localDate, LocalTime.of ( 23, 0 ), zoneId );
мы указываем позднее время как на следующий день в 1:00.
ZonedDateTime later = ZonedDateTime.of ( localDate.plusDays ( 1 ), LocalTime.of ( 1, 0 ), zoneId );
мы вычисляем Duration
таким же образом, как видели выше. Теперь мы получаем два часа, ожидаемых этим вопросом.
Duration duration = Duration.between ( sooner, later );
дамп в консоли.
System.out.println ( "sooner: " + sooner + " | later: " + later + " | duration: " + duration );
раньше: 2016-01-23T23:00-05: 00[Америка / Монреаль] / позже: 2016-01-24T01:00-05: 00[Америка / Монреаль] / продолжительность: PT2H
Летнее Время
если дата-время под рукой включало летнее время (DST) или другую такую аномалию, java.классы времени будут корректироваться по мере необходимости. Прочитайте класс doc для деталей.
о java.время
на java.время framework встроен в Java 8 и более поздние версии. Эти классы вытесняют беспокойных старых наследие дата-время такие классы, как java.util.Date
, Calendar
, & SimpleDateFormat
.
на Joda Времени, теперь режим обслуживания, советует миграцию в java.время классы.
чтобы узнать больше, см. В Oracle Учебник. И search Stack Overflow для многих примеров и объяснений. Спецификация в JSR 310.
вы можете обменять java.время объекты непосредственно с вашей базой данных. Используйте драйвер JDBC соответствуют JDBC 4.2 или позже. Нет необходимости в строках, нет необходимости в java.sql.*
классы.
где получить java.время занятий?
-
Java SE 8, Java SE 9, Java SE 10, и позже
- встроенный.
- часть стандартного API Java со встроенной реализацией.
- Java 9 добавляет некоторые незначительные функции и исправления.
-
Java SE 6 и Java SE 7
- большая часть java.функциональность времени обратно портирована на Java 6 & 7 в ThreeTen-Backport.
-
Android
- более поздние версии Android bundle реализации java.классы время.
- для более раннего Android ( ThreeTenABP проект приспосабливается ThreeTen-Backport (упоминалось выше). См.как использовать ThreeTenABP....
на ThreeTen-Extra проект расширяет java.время с дополнительными занятиями. Этот проект является испытательной площадкой для возможных будущих дополнений к java.время. Здесь вы можете найти полезные классы, такие как Interval
, YearWeek
, YearQuarter
и больше.
Java предоставляет статический метод System.currentTimeMillis()
. И это возвращает длинное значение, поэтому это хорошая ссылка. Многие другие классы принимают параметр timeInMillis, который также является длинным.
и многие люди считают, что проще использовать Джода Времени библиотека для выполнения расчетов по датам и времени.
какие типы использовать для выполнения этого в Java?
ответ: long
public class Stream {
public long startTime;
public long endTime;
public long getDuration() {
return endTime - startTime;
}
// I would add
public void start() {
startTime = System.currentTimeMillis();
}
public void stop() {
endTime = System.currentTimeMillis();
}
}
использование:
Stream s = ....
s.start();
// do something for a while
s.stop();
s.getDuration(); // gives the elapsed time in milliseconds.
Это мой прямой ответ на ваш первый вопрос.
для последней "заметки" я бы предложил вам использовать время Джоды. Он содержит интервал класс подходит для того, что вам нужно.
стоит отметить, что
- система.currentTimeMillis () имеет только миллисекундную точность в лучшем случае. На счету его может быть 16 МС на некоторых системах windows. Он имеет более низкую стоимость, что альтернативы
- система.nanoTime() является только микросекундным точным в большинстве систем и может прыгать на системах windows на 100 микросекунд (i.e иногда это не так точно, как кажется)
- календарь-очень дорогой способ расчета времени. (я могу думать только из XMLGregorianCalendar) иногда его наиболее подходящее решение, но имейте в виду, что вы должны только длительные интервалы времени.
Если вы пишете приложение, которое должно иметь дело с длительностью времени, пожалуйста, взгляните на Joda-Time, который имеет класс специально для обработки длительностей,интервалы, и периоды. Ваш getDuration()
метод выглядит так, как будто он может вернуть интервал времени Joda:
DateTime start = new DateTime(2004, 12, 25, 0, 0, 0, 0);
DateTime end = new DateTime(2005, 1, 1, 0, 0, 0, 0);
public Interval getInterval() {
Interval interval = new Interval(start, end);
}
Если вы предпочитаете использовать Java API календаря вы можете попробовать это,
Date startingTime = Calendar.getInstance().getTime();
//later on
Date now = Calendar.getInstance().getTime();
long timeElapsed = now.getTime() - startingTime.getTime();
Если вы получаете свои метки времени от System.currentTimeMillis()
, тогда ваши переменные времени должны быть длинные.
Byte Stream Reader Elapsed Time for 23.7 MB is 96 secs
import java.io.*;
import java.io.IOException;
import java.util.Scanner;
class ElaspedTimetoCopyAFileUsingByteStream
{
private long startTime = 0;
private long stopTime = 0;
private boolean running = false;
public void start()
{
this.startTime = System.currentTimeMillis();
this.running = true;
}
public void stop()
{
this.stopTime = System.currentTimeMillis();
this.running = false;
}
public long getElapsedTime()
{
long elapsed;
if (running) {
elapsed = (System.currentTimeMillis() - startTime);
}
else {
elapsed = (stopTime - startTime);
}
return elapsed;
}
public long getElapsedTimeSecs()
{
long elapsed;
if (running)
{
elapsed = ((System.currentTimeMillis() - startTime) / 1000);
}
else
{
elapsed = ((stopTime - startTime) / 1000);
}
return elapsed;
}
public static void main(String[] args) throws IOException
{
ElaspedTimetoCopyAFileUsingByteStream s = new ElaspedTimetoCopyAFileUsingByteStream();
s.start();
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream("vowels.txt"); // 23.7 MB File
out = new FileOutputStream("output.txt");
int c;
while ((c = in.read()) != -1) {
out.write(c);
}
}finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
s.stop();
System.out.println("elapsed time in seconds: " + s.getElapsedTimeSecs());
}
}
[Elapsed Time for Byte Stream Reader][1]
**Character Stream Reader Elapsed Time for 23.7 MB is 3 secs**
import java.io.*;
import java.io.IOException;
import java.util.Scanner;
class ElaspedTimetoCopyAFileUsingCharacterStream
{
private long startTime = 0;
private long stopTime = 0;
private boolean running = false;
public void start()
{
this.startTime = System.currentTimeMillis();
this.running = true;
}
public void stop()
{
this.stopTime = System.currentTimeMillis();
this.running = false;
}
public long getElapsedTime()
{
long elapsed;
if (running) {
elapsed = (System.currentTimeMillis() - startTime);
}
else {
elapsed = (stopTime - startTime);
}
return elapsed;
}
public long getElapsedTimeSecs()
{
long elapsed;
if (running)
{
elapsed = ((System.currentTimeMillis() - startTime) / 1000);
}
else
{
elapsed = ((stopTime - startTime) / 1000);
}
return elapsed;
}
public static void main(String[] args) throws IOException
{
ElaspedTimetoCopyAFileUsingCharacterStream s = new ElaspedTimetoCopyAFileUsingCharacterStream();
s.start();
FileReader in = null; // CharacterStream Reader
FileWriter out = null;
try {
in = new FileReader("vowels.txt"); // 23.7 MB
out = new FileWriter("output.txt");
int c;
while ((c = in.read()) != -1) {
out.write(c);
}
}finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
s.stop();
System.out.println("elapsed time in seconds: " + s.getElapsedTimeSecs());
}
}
[Elapsed Time for Character Stream Reader][2]
[1]: https://i.stack.imgur.com/hYo8y.png
[2]: https://i.stack.imgur.com/xPjCK.png
Я нашел этот код полезным при синхронизации вещей:
public class Et {
public Et() {
reset();
}
public void reset() {
t0=System.nanoTime();
}
public long t0() {
return t0;
}
public long dt() {
return System.nanoTime()-t0();
}
public double etms() {
return etms(dt());
}
@Override public String toString() {
return etms()+" ms.";
}
public static double etms(long dt) {
return dt/1000000.; // 1_000_000. breaks cobertura
}
private Long t0;
}
используйте этот:
SimpleDateFormat format = new SimpleDateFormat("HH:mm");
Date d1 = format.parse(strStartTime);
Date d2 = format.parse(strEndTime);
long diff = d2.getTime() - d1.getTime();
long diffSeconds,diffMinutes,diffHours;
if (diff > 0) {
diffSeconds = diff / 1000 % 60;
diffMinutes = diff / (60 * 1000) % 60;
diffHours = diff / (60 * 60 * 1000);
}
else{
long diffpos = (24*((60 * 60 * 1000))) + diff;
diffSeconds = diffpos / 1000 % 60;
diffMinutes = diffpos / (60 * 1000) % 60;
diffHours = (diffpos / (60 * 60 * 1000));
}
(также важно, что, например, если startTime это 23:00 и endTime 1:00, чтобы получить Продолжительность 2:00.)
часть "else" может получить его правильно
Я построил функцию форматирования на основе вещей, которые я украл так. Мне нужен был способ "профилирования"материала в сообщениях журнала, поэтому мне нужно было сообщение с фиксированной длиной.
public static String GetElapsed(long aInitialTime, long aEndTime, boolean aIncludeMillis)
{
StringBuffer elapsed = new StringBuffer();
Map<String, Long> units = new HashMap<String, Long>();
long milliseconds = aEndTime - aInitialTime;
long seconds = milliseconds / 1000;
long minutes = milliseconds / (60 * 1000);
long hours = milliseconds / (60 * 60 * 1000);
long days = milliseconds / (24 * 60 * 60 * 1000);
units.put("milliseconds", milliseconds);
units.put("seconds", seconds);
units.put("minutes", minutes);
units.put("hours", hours);
units.put("days", days);
if (days > 0)
{
long leftoverHours = hours % 24;
units.put("hours", leftoverHours);
}
if (hours > 0)
{
long leftoeverMinutes = minutes % 60;
units.put("minutes", leftoeverMinutes);
}
if (minutes > 0)
{
long leftoverSeconds = seconds % 60;
units.put("seconds", leftoverSeconds);
}
if (seconds > 0)
{
long leftoverMilliseconds = milliseconds % 1000;
units.put("milliseconds", leftoverMilliseconds);
}
elapsed.append(PrependZeroIfNeeded(units.get("days")) + " days ")
.append(PrependZeroIfNeeded(units.get("hours")) + " hours ")
.append(PrependZeroIfNeeded(units.get("minutes")) + " minutes ")
.append(PrependZeroIfNeeded(units.get("seconds")) + " seconds ")
.append(PrependZeroIfNeeded(units.get("milliseconds")) + " ms");
return elapsed.toString();
}
private static String PrependZeroIfNeeded(long aValue)
{
return aValue < 10 ? "0" + aValue : Long.toString(aValue);
}
и тестовый класс:
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import junit.framework.TestCase;
public class TimeUtilsTest extends TestCase
{
public void testGetElapsed()
{
long start = System.currentTimeMillis();
GregorianCalendar calendar = (GregorianCalendar) Calendar.getInstance();
calendar.setTime(new Date(start));
calendar.add(Calendar.MILLISECOND, 610);
calendar.add(Calendar.SECOND, 35);
calendar.add(Calendar.MINUTE, 5);
calendar.add(Calendar.DAY_OF_YEAR, 5);
long end = calendar.getTimeInMillis();
assertEquals("05 days 00 hours 05 minutes 35 seconds 610 ms", TimeUtils.GetElapsed(start, end, true));
}
}