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