diff --git a/src/java/org/apache/commons/lang/time/StopWatch.java b/src/java/org/apache/commons/lang/time/StopWatch.java new file mode 100644 index 000000000..f27dcdb0c --- /dev/null +++ b/src/java/org/apache/commons/lang/time/StopWatch.java @@ -0,0 +1,239 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 1999-2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Commons", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.commons.lang.time; + +/** + *

StopWatch provides a convenient API for timings.

+ * + *

The methods do not protect against inappropriate calls. Thus you + * can call stop before start, resume before suspend or unsplit before split. + * The results are indeterminate in these cases.

+ * + *

To start the watch, call {@link #start()}. At this point you can:

+ * + *

It is intended that the output methods {@link #toString()} and {@link #getTime()} + * should only be called after stop, split or suspend, however a suitable result will + * be returned at other points.

+ * + * @author Henri Yandell + * @author Stephen Colebourne + * @since 2.0 + * @version $Id: StopWatch.java,v 1.1 2002/12/22 22:59:58 scolebourne Exp $ + */ +public class StopWatch { + + private static final int MILLIS_IN_HOUR = 60 * 60 * 1000; + private static final int MILLIS_IN_MINUTE = 60 * 1000; + + /** The start time */ + private long startTime = -1; + /** The stop time */ + private long stopTime = -1; + + /** + *

Constructor.

+ */ + public StopWatch() { + } + + /** + *

Start the stopwatch.

+ * + *

This method starts a new timing session, clearing any previous values.

+ */ + public void start() { + stopTime = -1; + startTime = System.currentTimeMillis(); + } + + /** + *

Stop the stopwatch.

+ * + *

This method ends a new timing session, allowing the time to be retrieved.

+ */ + public void stop() { + stopTime = System.currentTimeMillis(); + } + + /** + *

Reset the stopwatch.

+ * + *

This method clears the internal values to allow the object to be reused.

+ */ + public void reset() { + startTime = -1; + stopTime = -1; + } + + /** + *

Split the time.

+ * + *

This method sets the stop time of the watch to allow a time to be extracted. + * The start time is unaffected, enabling {@link #unsplit()} to contine the + * timing from the original start point.

+ */ + public void split() { + stopTime = System.currentTimeMillis(); + } + + /** + *

Remove a split.

+ * + *

This method clears the stop time. The start time is unaffected, enabling + * timing from the original start point to continue.

+ */ + public void unsplit() { + stopTime = -1; + } + + /** + *

Suspend the stopwatch for later resumption.

+ * + *

This method suspends the watch until it is resumed. The watch will not include + * time between the suspend and resume calls in the total time.

+ */ + public void suspend() { + stopTime = System.currentTimeMillis(); + } + + /** + *

Resume the stopwatch after a suspend.

+ * + *

This method resumes the watch after it was suspended. The watch will not include + * time between the suspend and resume calls in the total time.

+ */ + public void resume() { + startTime += (System.currentTimeMillis() - stopTime); + stopTime = -1; + } + + /** + *

Get the time on the stopwatch.

+ * + *

This is either the time between start and latest split, between start + * and stop, or the time between the start and the moment this method is called.

+ * + * @return the time in milliseconds + */ + public long getTime() { + if (stopTime == -1) { + if (startTime == -1) { + return 0; + } + return (System.currentTimeMillis() - this.startTime); + } + return (this.stopTime - this.startTime); + } + + /** + *

Gets a summary of the time that the stopwatch recorded as a string.

+ * + *

The format used is ISO8601, + * hours:minutes:seconds.milliseconds.

+ * + * @return the time as a String + */ + public String toString() { + return StopWatch.toString(getTime()); + } + + /** + *

Get the time gap as a string.

+ * + *

The format used is ISO8601, + * hours:minutes:seconds.milliseconds.

+ * + * @return the time as a String + */ + public static String toString(long time) { + int hours, minutes, seconds, milliseconds; + hours = (int) (time / MILLIS_IN_HOUR); + time = time - (hours * MILLIS_IN_HOUR); + minutes = (int) (time / MILLIS_IN_MINUTE); + time = time - (minutes * MILLIS_IN_MINUTE); + seconds = (int) (time / 1000); + time = time - (seconds * 1000); + milliseconds = (int) time; + + StringBuffer buf = new StringBuffer(32); + buf.append(hours); + buf.append(':'); + if (minutes < 10) { + buf.append('0'); + } + buf.append(minutes); + buf.append(':'); + if (seconds < 10) { + buf.append('0'); + } + buf.append(seconds); + buf.append('.'); + if (milliseconds < 10) { + buf.append("00"); + } else if (milliseconds < 100) { + buf.append('0'); + } + buf.append(milliseconds); + return buf.toString(); + } + +} diff --git a/src/test/org/apache/commons/lang/time/StopWatchTest.java b/src/test/org/apache/commons/lang/time/StopWatchTest.java new file mode 100644 index 000000000..f5be5ce32 --- /dev/null +++ b/src/test/org/apache/commons/lang/time/StopWatchTest.java @@ -0,0 +1,171 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.commons.lang.time; + +import java.util.Date; +import java.util.Calendar; +import java.util.TimeZone; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; +import junit.textui.TestRunner; + +/** + * TestCase for StopWatch. + * + * @author Stephen Colebourne + * @version $Id: StopWatchTest.java,v 1.1 2002/12/22 22:59:58 scolebourne Exp $ + */ +public class StopWatchTest extends TestCase { + + public static void main(String[] args) { + TestRunner.run(suite()); + } + + public static Test suite() { + TestSuite suite = new TestSuite(StopWatchTest.class); + suite.setName("StopWatch Tests"); + return suite; + } + + public StopWatchTest(String s) { + super(s); + } + + public void testToString(){ + long time = 0; + assertEquals("0:00:00.000", StopWatch.toString(time)); + + time = 1; + assertEquals("0:00:00.001", StopWatch.toString(time)); + + time = 15; + assertEquals("0:00:00.015", StopWatch.toString(time)); + + time = 165; + assertEquals("0:00:00.165", StopWatch.toString(time)); + + time = 1675; + assertEquals("0:00:01.675", StopWatch.toString(time)); + + time = 13465; + assertEquals("0:00:13.465", StopWatch.toString(time)); + + time = 72789; + assertEquals("0:01:12.789", StopWatch.toString(time)); + + time = 12789 + 32 * 60000; + assertEquals("0:32:12.789", StopWatch.toString(time)); + + time = 12789 + 62 * 60000; + assertEquals("1:02:12.789", StopWatch.toString(time)); + } + + public void testStopWatchSimple(){ + StopWatch watch = new StopWatch(); + assertEquals(0, watch.getTime()); + + watch.start(); + try {Thread.sleep(550);} catch (InterruptedException ex) {} + watch.stop(); + long time = watch.getTime(); + assertEquals(time, watch.getTime()); + + assertTrue(time >= 500); + assertTrue(time < 650); + + watch.reset(); + assertEquals(0, watch.getTime()); + } + + public void testStopWatchSplit(){ + StopWatch watch = new StopWatch(); + watch.start(); + try {Thread.sleep(550);} catch (InterruptedException ex) {} + watch.split(); + long splitTime = watch.getTime(); + try {Thread.sleep(550);} catch (InterruptedException ex) {} + watch.unsplit(); + try {Thread.sleep(550);} catch (InterruptedException ex) {} + watch.stop(); + long totalTime = watch.getTime(); + +// System.err.println(splitTime +" "+totalTime); + assertTrue(splitTime >= 500); + assertTrue(splitTime < 650); + assertTrue(totalTime >= 1500); + assertTrue(totalTime < 1800); + } + + public void testStopWatchSuspend(){ + StopWatch watch = new StopWatch(); + watch.start(); + try {Thread.sleep(550);} catch (InterruptedException ex) {} + watch.suspend(); + long suspendTime = watch.getTime(); + try {Thread.sleep(550);} catch (InterruptedException ex) {} + watch.resume(); + try {Thread.sleep(550);} catch (InterruptedException ex) {} + watch.stop(); + long totalTime = watch.getTime(); + +// System.err.println(suspendTime +" "+totalTime); + assertTrue(suspendTime >= 500); + assertTrue(suspendTime < 600); + assertTrue(totalTime >= 1000); + assertTrue(totalTime < 1200); + } + +} diff --git a/src/test/org/apache/commons/lang/time/TimeTestSuite.java b/src/test/org/apache/commons/lang/time/TimeTestSuite.java index d19fec714..c58f0dff3 100644 --- a/src/test/org/apache/commons/lang/time/TimeTestSuite.java +++ b/src/test/org/apache/commons/lang/time/TimeTestSuite.java @@ -61,7 +61,7 @@ import junit.textui.TestRunner; * Test suite for the Time package. * * @author Stephen Colebourne - * @version $Id: TimeTestSuite.java,v 1.1 2002/12/18 23:30:19 scolebourne Exp $ + * @version $Id: TimeTestSuite.java,v 1.2 2002/12/22 22:59:58 scolebourne Exp $ */ public class TimeTestSuite extends TestCase { @@ -87,6 +87,7 @@ public class TimeTestSuite extends TestCase { suite.setName("Commons-Lang-Time Tests"); suite.addTest(CalendarUtilsTest.suite()); suite.addTest(DateUtilsTest.suite()); + suite.addTest(StopWatchTest.suite()); return suite; } }