10888a09821a98ac0680fad765217302858e70fa4Paul Duffin/*
20888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Copyright (C) 2008 The Guava Authors
30888a09821a98ac0680fad765217302858e70fa4Paul Duffin *
40888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Licensed under the Apache License, Version 2.0 (the "License");
50888a09821a98ac0680fad765217302858e70fa4Paul Duffin * you may not use this file except in compliance with the License.
60888a09821a98ac0680fad765217302858e70fa4Paul Duffin * You may obtain a copy of the License at
70888a09821a98ac0680fad765217302858e70fa4Paul Duffin *
80888a09821a98ac0680fad765217302858e70fa4Paul Duffin * http://www.apache.org/licenses/LICENSE-2.0
90888a09821a98ac0680fad765217302858e70fa4Paul Duffin *
100888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Unless required by applicable law or agreed to in writing, software
110888a09821a98ac0680fad765217302858e70fa4Paul Duffin * distributed under the License is distributed on an "AS IS" BASIS,
120888a09821a98ac0680fad765217302858e70fa4Paul Duffin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130888a09821a98ac0680fad765217302858e70fa4Paul Duffin * See the License for the specific language governing permissions and
140888a09821a98ac0680fad765217302858e70fa4Paul Duffin * limitations under the License.
150888a09821a98ac0680fad765217302858e70fa4Paul Duffin */
160888a09821a98ac0680fad765217302858e70fa4Paul Duffin
170888a09821a98ac0680fad765217302858e70fa4Paul Duffinpackage com.google.common.base;
180888a09821a98ac0680fad765217302858e70fa4Paul Duffin
190888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport static com.google.common.base.Preconditions.checkNotNull;
200888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport static com.google.common.base.Preconditions.checkState;
210888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport static java.util.concurrent.TimeUnit.DAYS;
220888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport static java.util.concurrent.TimeUnit.HOURS;
230888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport static java.util.concurrent.TimeUnit.MICROSECONDS;
240888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport static java.util.concurrent.TimeUnit.MILLISECONDS;
250888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport static java.util.concurrent.TimeUnit.MINUTES;
260888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport static java.util.concurrent.TimeUnit.NANOSECONDS;
270888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport static java.util.concurrent.TimeUnit.SECONDS;
280888a09821a98ac0680fad765217302858e70fa4Paul Duffin
290888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport com.google.common.annotations.Beta;
300888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport com.google.common.annotations.GwtCompatible;
310888a09821a98ac0680fad765217302858e70fa4Paul Duffin
320888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport java.util.concurrent.TimeUnit;
330888a09821a98ac0680fad765217302858e70fa4Paul Duffin
340888a09821a98ac0680fad765217302858e70fa4Paul Duffin/**
350888a09821a98ac0680fad765217302858e70fa4Paul Duffin * An object that measures elapsed time in nanoseconds. It is useful to measure
360888a09821a98ac0680fad765217302858e70fa4Paul Duffin * elapsed time using this class instead of direct calls to {@link
370888a09821a98ac0680fad765217302858e70fa4Paul Duffin * System#nanoTime} for a few reasons:
380888a09821a98ac0680fad765217302858e70fa4Paul Duffin *
390888a09821a98ac0680fad765217302858e70fa4Paul Duffin * <ul>
400888a09821a98ac0680fad765217302858e70fa4Paul Duffin * <li>An alternate time source can be substituted, for testing or performance
410888a09821a98ac0680fad765217302858e70fa4Paul Duffin *     reasons.
420888a09821a98ac0680fad765217302858e70fa4Paul Duffin * <li>As documented by {@code nanoTime}, the value returned has no absolute
430888a09821a98ac0680fad765217302858e70fa4Paul Duffin *     meaning, and can only be interpreted as relative to another timestamp
440888a09821a98ac0680fad765217302858e70fa4Paul Duffin *     returned by {@code nanoTime} at a different time. {@code Stopwatch} is a
450888a09821a98ac0680fad765217302858e70fa4Paul Duffin *     more effective abstraction because it exposes only these relative values,
460888a09821a98ac0680fad765217302858e70fa4Paul Duffin *     not the absolute ones.
470888a09821a98ac0680fad765217302858e70fa4Paul Duffin * </ul>
480888a09821a98ac0680fad765217302858e70fa4Paul Duffin *
490888a09821a98ac0680fad765217302858e70fa4Paul Duffin * <p>Basic usage:
500888a09821a98ac0680fad765217302858e70fa4Paul Duffin * <pre>
510888a09821a98ac0680fad765217302858e70fa4Paul Duffin *   Stopwatch stopwatch = Stopwatch.{@link #createStarted createStarted}();
520888a09821a98ac0680fad765217302858e70fa4Paul Duffin *   doSomething();
530888a09821a98ac0680fad765217302858e70fa4Paul Duffin *   stopwatch.{@link #stop stop}(); // optional
540888a09821a98ac0680fad765217302858e70fa4Paul Duffin *
550888a09821a98ac0680fad765217302858e70fa4Paul Duffin *   long millis = stopwatch.elapsed(MILLISECONDS);
560888a09821a98ac0680fad765217302858e70fa4Paul Duffin *
570888a09821a98ac0680fad765217302858e70fa4Paul Duffin *   log.info("time: " + stopwatch); // formatted string like "12.3 ms"</pre>
580888a09821a98ac0680fad765217302858e70fa4Paul Duffin *
590888a09821a98ac0680fad765217302858e70fa4Paul Duffin * <p>Stopwatch methods are not idempotent; it is an error to start or stop a
600888a09821a98ac0680fad765217302858e70fa4Paul Duffin * stopwatch that is already in the desired state.
610888a09821a98ac0680fad765217302858e70fa4Paul Duffin *
620888a09821a98ac0680fad765217302858e70fa4Paul Duffin * <p>When testing code that uses this class, use
630888a09821a98ac0680fad765217302858e70fa4Paul Duffin * {@link #createUnstarted(Ticker)} or {@link #createStarted(Ticker)} to
640888a09821a98ac0680fad765217302858e70fa4Paul Duffin * supply a fake or mock ticker.
650888a09821a98ac0680fad765217302858e70fa4Paul Duffin * <!-- TODO(kevinb): restore the "such as" --> This allows you to
660888a09821a98ac0680fad765217302858e70fa4Paul Duffin * simulate any valid behavior of the stopwatch.
670888a09821a98ac0680fad765217302858e70fa4Paul Duffin *
680888a09821a98ac0680fad765217302858e70fa4Paul Duffin * <p><b>Note:</b> This class is not thread-safe.
690888a09821a98ac0680fad765217302858e70fa4Paul Duffin *
700888a09821a98ac0680fad765217302858e70fa4Paul Duffin * @author Kevin Bourrillion
710888a09821a98ac0680fad765217302858e70fa4Paul Duffin * @since 10.0
720888a09821a98ac0680fad765217302858e70fa4Paul Duffin */
730888a09821a98ac0680fad765217302858e70fa4Paul Duffin@Beta
740888a09821a98ac0680fad765217302858e70fa4Paul Duffin@GwtCompatible(emulated = true)
750888a09821a98ac0680fad765217302858e70fa4Paul Duffinpublic final class Stopwatch {
760888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private final Ticker ticker;
770888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private boolean isRunning;
780888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private long elapsedNanos;
790888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private long startTick;
800888a09821a98ac0680fad765217302858e70fa4Paul Duffin
810888a09821a98ac0680fad765217302858e70fa4Paul Duffin  /**
820888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * Creates (but does not start) a new stopwatch using {@link System#nanoTime}
830888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * as its time source.
840888a09821a98ac0680fad765217302858e70fa4Paul Duffin   *
850888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * @since 15.0
860888a09821a98ac0680fad765217302858e70fa4Paul Duffin   */
870888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public static Stopwatch createUnstarted() {
880888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return new Stopwatch();
890888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
900888a09821a98ac0680fad765217302858e70fa4Paul Duffin
910888a09821a98ac0680fad765217302858e70fa4Paul Duffin  /**
920888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * Creates (but does not start) a new stopwatch, using the specified time
930888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * source.
940888a09821a98ac0680fad765217302858e70fa4Paul Duffin   *
950888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * @since 15.0
960888a09821a98ac0680fad765217302858e70fa4Paul Duffin   */
970888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public static Stopwatch createUnstarted(Ticker ticker) {
980888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return new Stopwatch(ticker);
990888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1000888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1010888a09821a98ac0680fad765217302858e70fa4Paul Duffin  /**
1020888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * Creates (and starts) a new stopwatch using {@link System#nanoTime}
1030888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * as its time source.
1040888a09821a98ac0680fad765217302858e70fa4Paul Duffin   *
1050888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * @since 15.0
1060888a09821a98ac0680fad765217302858e70fa4Paul Duffin   */
1070888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public static Stopwatch createStarted() {
1080888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return new Stopwatch().start();
1090888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1100888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1110888a09821a98ac0680fad765217302858e70fa4Paul Duffin  /**
1120888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * Creates (and starts) a new stopwatch, using the specified time
1130888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * source.
1140888a09821a98ac0680fad765217302858e70fa4Paul Duffin   *
1150888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * @since 15.0
1160888a09821a98ac0680fad765217302858e70fa4Paul Duffin   */
1170888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public static Stopwatch createStarted(Ticker ticker) {
1180888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return new Stopwatch(ticker).start();
1190888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1200888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1210888a09821a98ac0680fad765217302858e70fa4Paul Duffin  /**
1220888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * Creates (but does not start) a new stopwatch using {@link System#nanoTime}
1230888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * as its time source.
1240888a09821a98ac0680fad765217302858e70fa4Paul Duffin   *
1250888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * @deprecated Use {@link Stopwatch#createUnstarted()} instead. This
1260888a09821a98ac0680fad765217302858e70fa4Paul Duffin   *     constructor is scheduled to be removed in Guava release 17.0.
1270888a09821a98ac0680fad765217302858e70fa4Paul Duffin   */
1280888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Deprecated
1290888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public Stopwatch() {
1300888a09821a98ac0680fad765217302858e70fa4Paul Duffin    this(Ticker.systemTicker());
1310888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1320888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1330888a09821a98ac0680fad765217302858e70fa4Paul Duffin  /**
1340888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * Creates (but does not start) a new stopwatch, using the specified time
1350888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * source.
1360888a09821a98ac0680fad765217302858e70fa4Paul Duffin   *
1370888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * @deprecated Use {@link Stopwatch#createUnstarted(Ticker)} instead. This
1380888a09821a98ac0680fad765217302858e70fa4Paul Duffin   *     constructor is scheduled to be removed in Guava release 17.0.
1390888a09821a98ac0680fad765217302858e70fa4Paul Duffin   */
1400888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Deprecated
1410888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public Stopwatch(Ticker ticker) {
1420888a09821a98ac0680fad765217302858e70fa4Paul Duffin    this.ticker = checkNotNull(ticker, "ticker");
1430888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1440888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1450888a09821a98ac0680fad765217302858e70fa4Paul Duffin  /**
1460888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * Returns {@code true} if {@link #start()} has been called on this stopwatch,
1470888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * and {@link #stop()} has not been called since the last call to {@code
1480888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * start()}.
1490888a09821a98ac0680fad765217302858e70fa4Paul Duffin   */
1500888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public boolean isRunning() {
1510888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return isRunning;
1520888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1530888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1540888a09821a98ac0680fad765217302858e70fa4Paul Duffin  /**
1550888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * Starts the stopwatch.
1560888a09821a98ac0680fad765217302858e70fa4Paul Duffin   *
1570888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * @return this {@code Stopwatch} instance
1580888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * @throws IllegalStateException if the stopwatch is already running.
1590888a09821a98ac0680fad765217302858e70fa4Paul Duffin   */
1600888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public Stopwatch start() {
1610888a09821a98ac0680fad765217302858e70fa4Paul Duffin    checkState(!isRunning, "This stopwatch is already running.");
1620888a09821a98ac0680fad765217302858e70fa4Paul Duffin    isRunning = true;
1630888a09821a98ac0680fad765217302858e70fa4Paul Duffin    startTick = ticker.read();
1640888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return this;
1650888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1660888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1670888a09821a98ac0680fad765217302858e70fa4Paul Duffin  /**
1680888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * Stops the stopwatch. Future reads will return the fixed duration that had
1690888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * elapsed up to this point.
1700888a09821a98ac0680fad765217302858e70fa4Paul Duffin   *
1710888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * @return this {@code Stopwatch} instance
1720888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * @throws IllegalStateException if the stopwatch is already stopped.
1730888a09821a98ac0680fad765217302858e70fa4Paul Duffin   */
1740888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public Stopwatch stop() {
1750888a09821a98ac0680fad765217302858e70fa4Paul Duffin    long tick = ticker.read();
1760888a09821a98ac0680fad765217302858e70fa4Paul Duffin    checkState(isRunning, "This stopwatch is already stopped.");
1770888a09821a98ac0680fad765217302858e70fa4Paul Duffin    isRunning = false;
1780888a09821a98ac0680fad765217302858e70fa4Paul Duffin    elapsedNanos += tick - startTick;
1790888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return this;
1800888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1810888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1820888a09821a98ac0680fad765217302858e70fa4Paul Duffin  /**
1830888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * Sets the elapsed time for this stopwatch to zero,
1840888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * and places it in a stopped state.
1850888a09821a98ac0680fad765217302858e70fa4Paul Duffin   *
1860888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * @return this {@code Stopwatch} instance
1870888a09821a98ac0680fad765217302858e70fa4Paul Duffin   */
1880888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public Stopwatch reset() {
1890888a09821a98ac0680fad765217302858e70fa4Paul Duffin    elapsedNanos = 0;
1900888a09821a98ac0680fad765217302858e70fa4Paul Duffin    isRunning = false;
1910888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return this;
1920888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1930888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1940888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private long elapsedNanos() {
1950888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return isRunning ? ticker.read() - startTick + elapsedNanos : elapsedNanos;
1960888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1970888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1980888a09821a98ac0680fad765217302858e70fa4Paul Duffin  /**
1990888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * Returns the current elapsed time shown on this stopwatch, expressed
2000888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * in the desired time unit, with any fraction rounded down.
2010888a09821a98ac0680fad765217302858e70fa4Paul Duffin   *
2020888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * <p>Note that the overhead of measurement can be more than a microsecond, so
2030888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * it is generally not useful to specify {@link TimeUnit#NANOSECONDS}
2040888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * precision here.
2050888a09821a98ac0680fad765217302858e70fa4Paul Duffin   *
2060888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * @since 14.0 (since 10.0 as {@code elapsedTime()})
2070888a09821a98ac0680fad765217302858e70fa4Paul Duffin   */
2080888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public long elapsed(TimeUnit desiredUnit) {
2090888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return desiredUnit.convert(elapsedNanos(), NANOSECONDS);
2100888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2110888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2120888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private static TimeUnit chooseUnit(long nanos) {
2130888a09821a98ac0680fad765217302858e70fa4Paul Duffin    if (DAYS.convert(nanos, NANOSECONDS) > 0) {
2140888a09821a98ac0680fad765217302858e70fa4Paul Duffin      return DAYS;
2150888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
2160888a09821a98ac0680fad765217302858e70fa4Paul Duffin    if (HOURS.convert(nanos, NANOSECONDS) > 0) {
2170888a09821a98ac0680fad765217302858e70fa4Paul Duffin      return HOURS;
2180888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
2190888a09821a98ac0680fad765217302858e70fa4Paul Duffin    if (MINUTES.convert(nanos, NANOSECONDS) > 0) {
2200888a09821a98ac0680fad765217302858e70fa4Paul Duffin      return MINUTES;
2210888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
2220888a09821a98ac0680fad765217302858e70fa4Paul Duffin    if (SECONDS.convert(nanos, NANOSECONDS) > 0) {
2230888a09821a98ac0680fad765217302858e70fa4Paul Duffin      return SECONDS;
2240888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
2250888a09821a98ac0680fad765217302858e70fa4Paul Duffin    if (MILLISECONDS.convert(nanos, NANOSECONDS) > 0) {
2260888a09821a98ac0680fad765217302858e70fa4Paul Duffin      return MILLISECONDS;
2270888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
2280888a09821a98ac0680fad765217302858e70fa4Paul Duffin    if (MICROSECONDS.convert(nanos, NANOSECONDS) > 0) {
2290888a09821a98ac0680fad765217302858e70fa4Paul Duffin      return MICROSECONDS;
2300888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
2310888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return NANOSECONDS;
2320888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2330888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2340888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private static String abbreviate(TimeUnit unit) {
2350888a09821a98ac0680fad765217302858e70fa4Paul Duffin    switch (unit) {
2360888a09821a98ac0680fad765217302858e70fa4Paul Duffin      case NANOSECONDS:
2370888a09821a98ac0680fad765217302858e70fa4Paul Duffin        return "ns";
2380888a09821a98ac0680fad765217302858e70fa4Paul Duffin      case MICROSECONDS:
2390888a09821a98ac0680fad765217302858e70fa4Paul Duffin        return "\u03bcs"; // μs
2400888a09821a98ac0680fad765217302858e70fa4Paul Duffin      case MILLISECONDS:
2410888a09821a98ac0680fad765217302858e70fa4Paul Duffin        return "ms";
2420888a09821a98ac0680fad765217302858e70fa4Paul Duffin      case SECONDS:
2430888a09821a98ac0680fad765217302858e70fa4Paul Duffin        return "s";
2440888a09821a98ac0680fad765217302858e70fa4Paul Duffin      case MINUTES:
2450888a09821a98ac0680fad765217302858e70fa4Paul Duffin        return "min";
2460888a09821a98ac0680fad765217302858e70fa4Paul Duffin      case HOURS:
2470888a09821a98ac0680fad765217302858e70fa4Paul Duffin        return "h";
2480888a09821a98ac0680fad765217302858e70fa4Paul Duffin      case DAYS:
2490888a09821a98ac0680fad765217302858e70fa4Paul Duffin        return "d";
2500888a09821a98ac0680fad765217302858e70fa4Paul Duffin      default:
2510888a09821a98ac0680fad765217302858e70fa4Paul Duffin        throw new AssertionError();
2520888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
2530888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2540888a09821a98ac0680fad765217302858e70fa4Paul Duffin}
2550888a09821a98ac0680fad765217302858e70fa4Paul Duffin
256