/*******************************************************************************
* Australian National University Data Commons
* Copyright (C) 2013 The Australian National University
*
* This file is part of Australian National University Data Commons.
*
* Australian National University Data Commons is free software: you
* can redistribute it and/or modify it under the terms of the GNU
* General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package au.edu.anu.dcclient.stopwatch;
import static java.text.MessageFormat.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This class enables measuring the time elapsed by a task. This is done by calling the start method just before the code whose times are to be measured, and the end method
* just after. This class measures the time elapsed in milliseconds by using <code>System.currentTimeMillis()</code>. The difference in start and end times is the time it
* took for the code to execute. This time elapsed value can be returned as a String in the format <code>1 hours 2 minutes 3 seconds 4 ms</code>
*
* It is recommended that <code>end()</code> is called in a finally block of the code being measured.
*
* @see {@link System#currentTimeMillis()}
*/
public class StopWatch
{
private static final Logger LOGGER = LoggerFactory.getLogger(StopWatch.class);
long startTimeInMs = -1;
long endTimeInMs = -1;
/**
* Starts the stopwatch.
*/
public void start()
{
startTimeInMs = System.currentTimeMillis();
}
/**
* Ends the stopwatch.
*
* @throws RuntimeException
* when called before <code>start()</code>
*/
public void end()
{
if (startTimeInMs == -1)
throw new RuntimeException("end() cannot be called before start()");
endTimeInMs = System.currentTimeMillis();
}
/**
* Returns the time this stopwatch was started.
*
* @return Start time in millis
*/
public long getStartTimeInMs()
{
return startTimeInMs;
}
/**
* Returns the time this stopwatch was stopped.
*
* @return End time in millis
*/
public long getEndTimeInMs()
{
return endTimeInMs;
}
/**
* Returns if the <code>end()</code> method has been called.
*
* @return true if this stopwatch has been stopped, false otherwise.
*/
public boolean hasEnded()
{
return endTimeInMs != -1;
}
/**
* Gets the time elapsed in millis.
*
* @return the difference between end time and start time in millis
*/
public long getElapsedInMillis()
{
if (endTimeInMs == -1)
return System.currentTimeMillis() - this.startTimeInMs;
return endTimeInMs - startTimeInMs;
}
/**
* Gets the time elapsed in seconds.
*
* @return the difference between end time and start time in seconds
*/
public long getElapsedInSeconds()
{
return (getElapsedInMillis() / 1000);
}
/**
* Gets the time elapsed in the human readable format <code>1 hours 2 minutes 3 seconds 4 ms</code>.
*
* @return Time elapsed as String
*/
public String getFriendlyElapsed()
{
return getFriendlyTime(getElapsedInMillis());
}
/**
* Formats milliseconds into a human readable String in the format <code>1 hours 2 minutes 3 seconds 4 ms</code>.
*
* @param totalMillis
* milliseconds to convert into human readable String
*
* @return String representing the time
*/
private String getFriendlyTime(long totalMillis)
{
long millis = getElapsedInMillis() % 1000;
long secs = ((getElapsedInMillis() % (1000 * 60 * 60)) % (1000 * 60)) / 1000;
long mins = (getElapsedInMillis() % (1000 * 60 * 60)) / (1000 * 60);
long hours = getElapsedInMillis() / (1000 * 60 * 60);
return format("{0,number,integer} hours {1,number,integer} mins {2,number,integer} sec {3,number,integer} ms", hours, mins, secs, millis);
}
@Override
public String toString()
{
return getFriendlyElapsed();
}
}