162

How to convert a value from nanoseconds to seconds?

Here's the code segment:

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"); 
}}

The error is

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

What does this mean?

lospejos
  • 1,976
  • 3
  • 19
  • 35
phill
  • 13,434
  • 38
  • 105
  • 141
  • 5
    The error means that you can not instantiate the type `TimeUtil`, because it is an `enum` (enumerator). If you want to use `TimeUnit`, you should use `TimeUnit.NANOSECONDS.toSeconds(elapsedTime)` instead. Good luck! – Daniel Kvist Mar 21 '15 at 22:02

8 Answers8

375

TimeUnit Enum

The following expression uses the TimeUnit enum (Java 5 and later) to convert from nanoseconds to seconds:

TimeUnit.SECONDS.convert(elapsedTime, TimeUnit.NANOSECONDS)
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
pythonquick
  • 10,789
  • 6
  • 33
  • 28
  • 16
    Not that this method does not include fractions of a second. So 4.9999999, would simply be 4 seconds. – Dick Lucas Jan 30 '15 at 20:21
  • 1
    This is preferred because you should never write out 1 followed by a whole mess of 0's due to it being very error prone. – demongolem Feb 23 '16 at 18:56
  • 1
    you can write it like this elapsedTime = (end_time - start_time)/1e9; – Hasson Sep 13 '16 at 23:48
  • 1
    If I stay 59 minutes and 50 seconds it still says 0h elapsed... Which is not ideal. So is there any way to make this method work with fractions? – user1156544 Feb 28 '17 at 13:47
214

Well, you could just divide by 1,000,000,000:

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

If you use TimeUnit to convert, you'll get your result as a long, so you'll lose decimal precision but maintain whole number precision.

Ewoks
  • 12,285
  • 8
  • 58
  • 67
Adam Rosenfield
  • 390,455
  • 97
  • 512
  • 589
  • I would change make 1000000000 a double to force double precision division. – Steve Kuo May 29 '09 at 03:06
  • 2
    1000000000.0 is already a double; a float constant would be 1000000000.0f. – Adam Rosenfield May 29 '09 at 03:09
  • 82
    But what if the number of nanoseconds in a second changes? :P – geofftnz May 29 '09 at 03:17
  • @geofftnz I hope this was joke. – Display Name May 19 '13 at 10:54
  • 1
    Of course, this answer doesn't use the TimeUnit enum as requested. – Tim Bender Jul 24 '13 at 22:03
  • 9
    This answer is now wrong - `convert()` and the `toFoo()` methods all return `long`s now http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/TimeUnit.html – Riking Jul 30 '13 at 01:58
  • 2
    Riking is not joking, this answer is now wrong in that TimeUnit methods return longs (not integers); the code sample still works, but is bad practice (a hard-coded 10-digit number is easy to mess up or change without noticing). pythonquick's answer below is the preferred expression. – mbarrows Oct 08 '13 at 21:54
  • 3
    @mbarrows However this answer is still *right* in that the `TimeUnit` solution results in a loss of specificity. `TimeUnit.SECONDS.convert(500, TimeUnit.MILLISECONDS);` will return `0`, not `0.5`. It simply depends on your use-case which of these is preferable. – nbrooks Aug 07 '14 at 20:42
  • @nbrooks A very good point, though in my experience, if you're reducing the granularity of your time units, it's either because you need it to be human readable or you don't care about that level of precision. Either usually means losing the decimal is fine. – mbarrows Aug 08 '14 at 04:03
  • 18
    Thoroughly agree with @nbrooks here. Using TimeUnit will not output fractions of a second, instead returning 0. If you don't want to use a hard coded 10 digit number then use something like 1E9. For example : `double seconds = ((double) nanoseconds) / 1E9;` I would do this every time as a personal preference. – TechTrip Aug 14 '14 at 03:48
  • 3
    Use this method over the TimeUnit Enum method if you would like fractions of a second. Using the TimeUnit Enum doesn't even round to the nearest second, it essentially just chops off the fractions of a second. So 4.9999999, would simply be 4. – Dick Lucas Jan 30 '15 at 20:20
  • 1
    @geofftnz: That's why the "magic number" should be externalised and read from a 23-layer deep XML configuration file on each use. – Mark K Cowan Nov 25 '16 at 17:32
  • 2
    @MarkKCowan static configuration files are deprecated, you should call the TimeConversion microservice. – geofftnz Dec 01 '16 at 08:11
  • 1
    @geofftnz no you should call a UnitConversionAdapter which proxies to the TimeConversion μservice – Mark K Cowan Dec 01 '16 at 11:42
61

TimeUnit is an enum, so you can't create a new one.

The following will convert 1000000000000ns to seconds.

TimeUnit.NANOSECONDS.toSeconds(1000000000000L);
Nick Veys
  • 23,458
  • 4
  • 47
  • 64
  • 4
    I believe it is 10e+9 not 1e+12! – Adam Arold Aug 27 '12 at 19:06
  • 8
    This is a pretty late reply, but the number in the example isn’t the number of nanos in a second, it’s just a number to convert. The whole idea is to not have to know those values. – Nick Veys Mar 12 '14 at 18:31
  • 2
    I think this should be the accepted answer. Using toXxx() is preferable to using convert() because with convert() it's not obvious which direction the conversion happens, whereas with toXxx() it is. – Klitos Kyriacou Dec 21 '15 at 12:27
22

To reduce verbosity, you can use a static import:

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

-and henceforth just type

NANOSECONDS.toSeconds(elapsedTime);
Zoltán
  • 21,321
  • 14
  • 93
  • 134
7

You should write :

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

Assigning the endTime in a variable might cause a few nanoseconds. In this approach you will get the exact elapsed time.

And then:

TimeUnit.SECONDS.convert(estimatedTime, TimeUnit.NANOSECONDS)
4

This will convert a time to seconds in a double format, which is more precise than an integer value:

double elapsedTimeInSeconds = TimeUnit.MILLISECONDS.convert(elapsedTime, TimeUnit.NANOSECONDS) / 1000.0;
Ayaz Alifov
  • 8,334
  • 4
  • 61
  • 56
3

JDK9+ solution using java.time.Duration

Duration.ofNanos(1_000_000L).toSeconds()

https://docs.oracle.com/javase/9/docs/api/java/time/Duration.html#ofNanos-long-

https://docs.oracle.com/javase/9/docs/api/java/time/Duration.html#toSeconds--

1

In Java 8 or Kotlin, I use Duration.ofNanos(1_000_000_000) like

val duration = Duration.ofNanos(1_000_000_000)
logger.info(String.format("%d %02dm %02ds %03d",
                elapse, duration.toMinutes(), duration.toSeconds(), duration.toMillis()))

Read more https://docs.oracle.com/javase/8/docs/api/java/time/Duration.html

nokieng
  • 1,858
  • 20
  • 24