LookingI am looking for input on my code for a Stopwatch utility written in Java.
/**
* File: Stopwatch.java
*/
package org.me.mystuff;
import java.util.concurrent.TimeUnit;
public class Stopwatch {
/**
* The start timestamp, as determined by a call to {@code System.nanoTime}.
*/
private long start;
/**
* The total elapsed time recorded so far in nanoseconds (raw value).
*/
private long elapsed;
/**
* Whether or not the stopwatch is running.
*/
private boolean running;
/**
* Constructs a new {@code Stopwatch} instance.
*/
public Stopwatch() {
reset();
}
/**
* Stops time interval measurement, resets the elapsed time to zero, and
* starts measuring time again.
*
* <p>
* This is a convenience method equivalent to calling {@code reset} followed
* by {@code start}.
*/
public void restart() {
reset();
start();
}
/**
* Stops time interval measurement and resets the elapsed time value to
* zero.
*/
public void reset() {
running = false;
start = 0;
elapsed = 0;
}
/**
* Initializes a new {@code Stopwatch} instance, sets the elapsed time value
* to zero, and starts measuring elapsed time.
*
* @return a running {@code Stopwatch} instance
*/
public static Stopwatch startNew() {
final var s = new Stopwatch();
s.start();
return s;
}
/**
* Starts, or resumes, measuring elapsed time for an interval.
*/
public void start() {
// Calling start() on a running stopwatch is a no-op.
if (!isRunning()) {
running = true;
start = start <= 0 ? System.nanoTime() : System.nanoTime() - elapsed;
}
}
/**
* Stops measuring elapsed time for an interval.
*/
public void stop() {
// Calling stop() on a stopped stopwatch is a no-op.
if (isRunning()) {
elapsed = System.nanoTime() - start;
running = false;
}
}
/**
* Returns the elapsed time measured so far by this stopwatch in the
* specified {@code TimeUnit}.
*
* @param timeUnit
* the desired time unit
* @return the duration in the specified time unit
*/
public double elapsed(TimeUnit timeUnit) {
// If the stopwatch is running, compute and return the current timestamp.
// Otherwise, just return the timestamp as of the last call to stop().
final long duration = isRunning() ? System.nanoTime() - start : elapsed;
return UnitConverter.convert(duration, timeUnit);
}
/**
* Returns {@code true} if the stopwatch is currently running.
*
* @return {@code true} if this stopwatch is running
*/
public boolean isRunning() {
return running;
}
/**
* Returns a string representation of the elapsed time measured so far by
* this stopwatch, expressed in milliseconds using two decimal places.
*
* <p>
* Example: 1.2345 milliseconds would return a string equal to
* {@code "1.23 ms"}.
*
* <p>
* This is a convenience method that simplifies querying the stopwatch for
* reporting purposes.
*/
@Override
public String toString() {
final double duration = elapsed(TimeUnit.MILLISECONDS);
final double rounded = Math.round(duration * 100d) / 100d;
return String.valueOf(rounded).concat(unit);
}
/**
* This class is an internal utility to supplement the stopwatch's unit
* conversion operations.
*/
private static class UnitConverter {
/**
* The number of nanoseconds in a millisecond.
*/
static final double NANOS_PER_MILLI = 1e6;
/**
* The number of nanoseconds in a second.
*/
static final double NANOS_PER_SECOND = 1e9;
/**
* The number of nanoseconds in a minute.
*/
static final double NANOS_PER_MINUTE = 6e10;
/**
* The number of nanoseconds in an hour.
*/
static final double NANOS_PER_HOUR = 3.6e12;
/**
* Converts the specified nanosecond value to the specified time unit
* and returns the result.
*
* @param nanoTime
* the value to convert (in nanoseconds)
* @param toUnit
* the desired time unit
* @return the converted value
*/
static double convert(long nanoTime, TimeUnit toUnit) {
switch (toUnit) {
case MILLISECONDS:
return toMillis(nanoTime);
case SECONDS:
return toSeconds(nanoTime);
case MINUTES:
return toMinutes(nanoTime);
case HOURS:
return toHours(nanoTime);
default:
throw new IllegalArgumentException("no valid time unit specified");
}
}
static double toMillis(long nanos) {
return nanos / NANOS_PER_MILLI;
}
static double toSeconds(long nanos) {
return nanos / NANOS_PER_SECOND;
}
static double toMinutes(long nanos) {
return nanos / NANOS_PER_MINUTE;
}
static double toHours(long nanos) {
return nanos / NANOS_PER_HOUR;
}
}
}
/**
* File: Stopwatch.java
*/
package org.me.mystuff;
import java.util.concurrent.TimeUnit;
public class Stopwatch {
/**
* The start timestamp, as determined by a call to {@code System.nanoTime}.
*/
private long start;
/**
* The total elapsed time recorded so far in nanoseconds (raw value).
*/
private long elapsed;
/**
* Whether or not the stopwatch is running.
*/
private boolean running;
/**
* Constructs a new {@code Stopwatch} instance.
*/
public Stopwatch() {
reset();
}
/**
* Stops time interval measurement, resets the elapsed time to zero, and
* starts measuring time again.
*
* <p>
* This is a convenience method equivalent to calling {@code reset} followed
* by {@code start}.
*/
public void restart() {
reset();
start();
}
/**
* Stops time interval measurement and resets the elapsed time value to
* zero.
*/
public void reset() {
running = false;
start = 0;
elapsed = 0;
}
/**
* Initializes a new {@code Stopwatch} instance, sets the elapsed time value
* to zero, and starts measuring elapsed time.
*
* @return a running {@code Stopwatch} instance
*/
public static Stopwatch startNew() {
final var s = new Stopwatch();
s.start();
return s;
}
/**
* Starts, or resumes, measuring elapsed time for an interval.
*/
public void start() {
// Calling start() on a running stopwatch is a no-op.
if (!isRunning()) {
running = true;
start = start <= 0 ? System.nanoTime() : System.nanoTime() - elapsed;
}
}
/**
* Stops measuring elapsed time for an interval.
*/
public void stop() {
// Calling stop() on a stopped stopwatch is a no-op.
if (isRunning()) {
elapsed = System.nanoTime() - start;
running = false;
}
}
/**
* Returns the elapsed time measured so far by this stopwatch in the
* specified {@code TimeUnit}.
*
* @param timeUnit
* the desired time unit
* @return the duration in the specified time unit
*/
public double elapsed(TimeUnit timeUnit) {
// If the stopwatch is running, compute and return the current timestamp.
// Otherwise, just return the timestamp as of the last call to stop().
final long duration = isRunning() ? System.nanoTime() - start : elapsed;
return UnitConverter.convert(duration, timeUnit);
}
/**
* Returns {@code true} if the stopwatch is currently running.
*
* @return {@code true} if this stopwatch is running
*/
public boolean isRunning() {
return running;
}
/**
* Returns a string representation of the elapsed time measured so far by
* this stopwatch, expressed in milliseconds using two decimal places.
*
* <p>
* Example: 1.2345 milliseconds would return a string equal to
* {@code "1.23 ms"}.
*
* <p>
* This is a convenience method that simplifies querying the stopwatch for
* reporting purposes.
*/
@Override
public String toString() {
final double duration = elapsed(TimeUnit.MILLISECONDS);
final double rounded = Math.round(duration * 100d) / 100d;
return String.valueOf(rounded).concat(unit);
}
/**
* This class is an internal utility to supplement the stopwatch's unit
* conversion operations.
*/
private static class UnitConverter {
/**
* The number of nanoseconds in a millisecond.
*/
static final double NANOS_PER_MILLI = 1e6;
/**
* The number of nanoseconds in a second.
*/
static final double NANOS_PER_SECOND = 1e9;
/**
* The number of nanoseconds in a minute.
*/
static final double NANOS_PER_MINUTE = 6e10;
/**
* The number of nanoseconds in an hour.
*/
static final double NANOS_PER_HOUR = 3.6e12;
/**
* Converts the specified nanosecond value to the specified time unit
* and returns the result.
*
* @param nanoTime
* the value to convert (in nanoseconds)
* @param toUnit
* the desired time unit
* @return the converted value
*/
static double convert(long nanoTime, TimeUnit toUnit) {
switch (toUnit) {
case MILLISECONDS:
return toMillis(nanoTime);
case SECONDS:
return toSeconds(nanoTime);
case MINUTES:
return toMinutes(nanoTime);
case HOURS:
return toHours(nanoTime);
default:
throw new IllegalArgumentException("no valid time unit specified");
}
}
static double toMillis(long nanos) {
return nanos / NANOS_PER_MILLI;
}
static double toSeconds(long nanos) {
return nanos / NANOS_PER_SECOND;
}
static double toMinutes(long nanos) {
return nanos / NANOS_PER_MINUTE;
}
static double toHours(long nanos) {
return nanos / NANOS_PER_HOUR;
}
}
}