Как преобразовать наносекунды в секунды, используя перечисление TimeUnit?

145

Как преобразовать значение из наносекунд в секунды?

Вот сегмент кода:

import java.io.*;
import java.util.concurrent.*; 
..

class Stamper { 

public static void main (String[] args) { 
long start = System.nanoTime(); 
//some try with nested loops 
long end = System.nanoTime(); 
long elapsedTime = end - start;

System.out.println("elapsed: " + elapsedTime + "nano seconds\n");

//convert to seconds 
TimeUnit seconds = new TimeUnit(); 
System.out.println("which is " + seconds.toSeconds(elapsedTime) + " seconds"); 
}}

Ошибка

Stamper.java:16:  enum types may not be instantiated.

Что это значит?

Phill
источник
4
Ошибка означает, что вы не можете создать экземпляр типа TimeUtil, потому что это enum(перечислитель). Если вы хотите использовать TimeUnit, вы должны использовать TimeUnit.NANOSECONDS.toSeconds(elapsedTime)вместо этого. Удачи!
Даниэль Квист

Ответы:

200

Ну, вы можете просто разделить на 1 000 000 000:

long elapsedTime = end - start;
double seconds = (double)elapsedTime / 1_000_000_000.0;

Если вы используете TimeUnitпреобразование, вы получите длинный результат, так что вы потеряете десятичную точность, но сохраните точность целых чисел.

Адам Розенфилд
источник
78
Но что, если количество наносекунд в секунду изменится? : P
geofftnz
9
Этот ответ теперь неверен - convert()и toFoo()все методы возвращают longs теперь docs.oracle.com/javase/6/docs/api/java/util/concurrent/…
Riking
3
@mbarrows Однако этот ответ по-прежнему прав в том, что TimeUnitрешение приводит к потере специфичности. TimeUnit.SECONDS.convert(500, TimeUnit.MILLISECONDS);вернется 0, нет 0.5. Это просто зависит от вашего варианта использования, который из них предпочтительнее.
nbrooks
17
Полностью согласен с @nbrooks здесь. Использование TimeUnit не будет выводить доли секунды, вместо этого возвращается 0. Если вы не хотите использовать жестко запрограммированное 10-значное число, используйте что-то вроде 1E9. Например: double seconds = ((double) nanoseconds) / 1E9; я бы делал это каждый раз как личное предпочтение.
TechTrip
3
Используйте этот метод над методом Enum TimeUnit, если вы хотите, чтобы доли секунды. Использование TimeUnit Enum даже не округляет до ближайшей секунды, по сути, оно просто отсекает доли секунды. Так что 4.9999999, будет просто 4.
Дик Лукас
354

TimeUnit Enum

Следующее выражение использует TimeUnitenum (Java 5 и более поздние версии) для преобразования из наносекунд в секунды:

TimeUnit.SECONDS.convert(elapsedTime, TimeUnit.NANOSECONDS)
pythonquick
источник
14
Не то, чтобы этот метод не включал доли секунды. Так что 4.9999999, будет просто 4 секунды.
Дик Лукас
1
Это предпочтительнее, потому что вы никогда не должны выписывать 1, за которым следует целый беспорядок, потому что он очень подвержен ошибкам.
демонголем
1
Вы можете написать это так: elapsedTime = (end_time - start_time) / 1e9;
Хэссон
1
Если я остаюсь 59 минут и 50 секунд, он все еще говорит, что прошло 0 часов ... Что не идеально. Так есть ли способ заставить этот метод работать с дробями?
user1156544
58

TimeUnit - это перечисление, поэтому вы не можете создать новый.

Следующее преобразует 1000000000000ns в секунды.

TimeUnit.NANOSECONDS.toSeconds(1000000000000L);
Ник Вейс
источник
4
Я считаю, что это 10e + 9, а не 1e + 12!
Адам Арольд
8
Это довольно поздний ответ, но число в примере - это не количество наносигналов в секунду, это просто число для преобразования. Вся идея состоит в том, чтобы не знать эти ценности.
Ник Вейс
2
Я думаю, что это должен быть принятый ответ. Использование toXxx () предпочтительнее использования convert (), потому что с convert () не очевидно, в каком направлении происходит преобразование, тогда как с toXxx () это так.
Klitos Kyriacou
21

Чтобы уменьшить многословность, вы можете использовать статический импорт:

import static java.util.concurrent.TimeUnit.NANOSECONDS;

-и впредь просто типа

NANOSECONDS.toSeconds(elapsedTime);
Золтан
источник
6

Вы должны написать:

    long startTime = System.nanoTime();        
    long estimatedTime = System.nanoTime() - startTime;

Назначение endTime в переменной может вызвать несколько наносекунд. При таком подходе вы получите точное истекшее время.

А потом:

TimeUnit.SECONDS.convert(estimatedTime, TimeUnit.NANOSECONDS)
Лалит Нараян Мишра
источник
4

Это преобразует время в секунды в двойном формате, который является более точным, чем целочисленное значение:

double elapsedTimeInSeconds = TimeUnit.MILLISECONDS.convert(elapsedTime, TimeUnit.NANOSECONDS) / 1000.0;
Аяз Алифов
источник