1 /*
   2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   3  *
   4  * This code is free software; you can redistribute it and/or modify it
   5  * under the terms of the GNU General Public License version 2 only, as
   6  * published by the Free Software Foundation.  Oracle designates this
   7  * particular file as subject to the "Classpath" exception as provided
   8  * by Oracle in the LICENSE file that accompanied this code.
   9  *
  10  * This code is distributed in the hope that it will be useful, but WITHOUT
  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  */
  24 
  25 /*
  26  * This file is available under and governed by the GNU General Public
  27  * License version 2 only, as published by the Free Software Foundation.
  28  * However, the following notice accompanied the original version of this
  29  * file:
  30  *
  31  * Written by Doug Lea with assistance from members of JCP JSR-166
  32  * Expert Group and released to the public domain, as explained at
  33  * http://creativecommons.org/publicdomain/zero/1.0/
  34  */
  35 
  36 package java.util.concurrent;
  37 
  38 import java.time.temporal.ChronoUnit;
  39 import java.util.Objects;
  40 
  41 /**
  42  * A {@code TimeUnit} represents time durations at a given unit of
  43  * granularity and provides utility methods to convert across units,
  44  * and to perform timing and delay operations in these units.  A
  45  * {@code TimeUnit} does not maintain time information, but only
  46  * helps organize and use time representations that may be maintained
  47  * separately across various contexts.  A nanosecond is defined as one
  48  * thousandth of a microsecond, a microsecond as one thousandth of a
  49  * millisecond, a millisecond as one thousandth of a second, a minute
  50  * as sixty seconds, an hour as sixty minutes, and a day as twenty four
  51  * hours.
  52  *
  53  * <p>A {@code TimeUnit} is mainly used to inform time-based methods
  54  * how a given timing parameter should be interpreted. For example,
  55  * the following code will timeout in 50 milliseconds if the {@link
  56  * java.util.concurrent.locks.Lock lock} is not available:
  57  *
  58  * <pre> {@code
  59  * Lock lock = ...;
  60  * if (lock.tryLock(50L, TimeUnit.MILLISECONDS)) ...}</pre>
  61  *
  62  * while this code will timeout in 50 seconds:
  63  * <pre> {@code
  64  * Lock lock = ...;
  65  * if (lock.tryLock(50L, TimeUnit.SECONDS)) ...}</pre>
  66  *
  67  * Note however, that there is no guarantee that a particular timeout
  68  * implementation will be able to notice the passage of time at the
  69  * same granularity as the given {@code TimeUnit}.
  70  *
  71  * @since 1.5
  72  * @author Doug Lea
  73  */
  74 public enum TimeUnit {
  75     /**
  76      * Time unit representing one thousandth of a microsecond.
  77      */
  78     NANOSECONDS {
  79         public long toNanos(long d)   { return d; }
  80         public long toMicros(long d)  { return d/(C1/C0); }
  81         public long toMillis(long d)  { return d/(C2/C0); }
  82         public long toSeconds(long d) { return d/(C3/C0); }
  83         public long toMinutes(long d) { return d/(C4/C0); }
  84         public long toHours(long d)   { return d/(C5/C0); }
  85         public long toDays(long d)    { return d/(C6/C0); }
  86         public long convert(long d, TimeUnit u) { return u.toNanos(d); }
  87         int excessNanos(long d, long m) { return (int)(d - (m*C2)); }
  88     },
  89 
  90     /**
  91      * Time unit representing one thousandth of a millisecond.
  92      */
  93     MICROSECONDS {
  94         public long toNanos(long d)   { return x(d, C1/C0, MAX/(C1/C0)); }
  95         public long toMicros(long d)  { return d; }
  96         public long toMillis(long d)  { return d/(C2/C1); }
  97         public long toSeconds(long d) { return d/(C3/C1); }
  98         public long toMinutes(long d) { return d/(C4/C1); }
  99         public long toHours(long d)   { return d/(C5/C1); }
 100         public long toDays(long d)    { return d/(C6/C1); }
 101         public long convert(long d, TimeUnit u) { return u.toMicros(d); }
 102         int excessNanos(long d, long m) { return (int)((d*C1) - (m*C2)); }
 103     },
 104 
 105     /**
 106      * Time unit representing one thousandth of a second.
 107      */
 108     MILLISECONDS {
 109         public long toNanos(long d)   { return x(d, C2/C0, MAX/(C2/C0)); }
 110         public long toMicros(long d)  { return x(d, C2/C1, MAX/(C2/C1)); }
 111         public long toMillis(long d)  { return d; }
 112         public long toSeconds(long d) { return d/(C3/C2); }
 113         public long toMinutes(long d) { return d/(C4/C2); }
 114         public long toHours(long d)   { return d/(C5/C2); }
 115         public long toDays(long d)    { return d/(C6/C2); }
 116         public long convert(long d, TimeUnit u) { return u.toMillis(d); }
 117         int excessNanos(long d, long m) { return 0; }
 118     },
 119 
 120     /**
 121      * Time unit representing one second.
 122      */
 123     SECONDS {
 124         public long toNanos(long d)   { return x(d, C3/C0, MAX/(C3/C0)); }
 125         public long toMicros(long d)  { return x(d, C3/C1, MAX/(C3/C1)); }
 126         public long toMillis(long d)  { return x(d, C3/C2, MAX/(C3/C2)); }
 127         public long toSeconds(long d) { return d; }
 128         public long toMinutes(long d) { return d/(C4/C3); }
 129         public long toHours(long d)   { return d/(C5/C3); }
 130         public long toDays(long d)    { return d/(C6/C3); }
 131         public long convert(long d, TimeUnit u) { return u.toSeconds(d); }
 132         int excessNanos(long d, long m) { return 0; }
 133     },
 134 
 135     /**
 136      * Time unit representing sixty seconds.
 137      * @since 1.6
 138      */
 139     MINUTES {
 140         public long toNanos(long d)   { return x(d, C4/C0, MAX/(C4/C0)); }
 141         public long toMicros(long d)  { return x(d, C4/C1, MAX/(C4/C1)); }
 142         public long toMillis(long d)  { return x(d, C4/C2, MAX/(C4/C2)); }
 143         public long toSeconds(long d) { return x(d, C4/C3, MAX/(C4/C3)); }
 144         public long toMinutes(long d) { return d; }
 145         public long toHours(long d)   { return d/(C5/C4); }
 146         public long toDays(long d)    { return d/(C6/C4); }
 147         public long convert(long d, TimeUnit u) { return u.toMinutes(d); }
 148         int excessNanos(long d, long m) { return 0; }
 149     },
 150 
 151     /**
 152      * Time unit representing sixty minutes.
 153      * @since 1.6
 154      */
 155     HOURS {
 156         public long toNanos(long d)   { return x(d, C5/C0, MAX/(C5/C0)); }
 157         public long toMicros(long d)  { return x(d, C5/C1, MAX/(C5/C1)); }
 158         public long toMillis(long d)  { return x(d, C5/C2, MAX/(C5/C2)); }
 159         public long toSeconds(long d) { return x(d, C5/C3, MAX/(C5/C3)); }
 160         public long toMinutes(long d) { return x(d, C5/C4, MAX/(C5/C4)); }
 161         public long toHours(long d)   { return d; }
 162         public long toDays(long d)    { return d/(C6/C5); }
 163         public long convert(long d, TimeUnit u) { return u.toHours(d); }
 164         int excessNanos(long d, long m) { return 0; }
 165     },
 166 
 167     /**
 168      * Time unit representing twenty four hours.
 169      * @since 1.6
 170      */
 171     DAYS {
 172         public long toNanos(long d)   { return x(d, C6/C0, MAX/(C6/C0)); }
 173         public long toMicros(long d)  { return x(d, C6/C1, MAX/(C6/C1)); }
 174         public long toMillis(long d)  { return x(d, C6/C2, MAX/(C6/C2)); }
 175         public long toSeconds(long d) { return x(d, C6/C3, MAX/(C6/C3)); }
 176         public long toMinutes(long d) { return x(d, C6/C4, MAX/(C6/C4)); }
 177         public long toHours(long d)   { return x(d, C6/C5, MAX/(C6/C5)); }
 178         public long toDays(long d)    { return d; }
 179         public long convert(long d, TimeUnit u) { return u.toDays(d); }
 180         int excessNanos(long d, long m) { return 0; }
 181     };
 182 
 183     // Handy constants for conversion methods
 184     static final long C0 = 1L;
 185     static final long C1 = C0 * 1000L;
 186     static final long C2 = C1 * 1000L;
 187     static final long C3 = C2 * 1000L;
 188     static final long C4 = C3 * 60L;
 189     static final long C5 = C4 * 60L;
 190     static final long C6 = C5 * 24L;
 191 
 192     static final long MAX = Long.MAX_VALUE;
 193 
 194     /**
 195      * Scale d by m, checking for overflow.
 196      * This has a short name to make above code more readable.
 197      */
 198     static long x(long d, long m, long over) {
 199         if (d > +over) return Long.MAX_VALUE;
 200         if (d < -over) return Long.MIN_VALUE;
 201         return d * m;
 202     }
 203 
 204     // To maintain full signature compatibility with 1.5, and to improve the
 205     // clarity of the generated javadoc (see 6287639: Abstract methods in
 206     // enum classes should not be listed as abstract), method convert
 207     // etc. are not declared abstract but otherwise act as abstract methods.
 208 
 209     /**
 210      * Converts the given time duration in the given unit to this unit.
 211      * Conversions from finer to coarser granularities truncate, so
 212      * lose precision. For example, converting {@code 999} milliseconds
 213      * to seconds results in {@code 0}. Conversions from coarser to
 214      * finer granularities with arguments that would numerically
 215      * overflow saturate to {@code Long.MIN_VALUE} if negative or
 216      * {@code Long.MAX_VALUE} if positive.
 217      *
 218      * <p>For example, to convert 10 minutes to milliseconds, use:
 219      * {@code TimeUnit.MILLISECONDS.convert(10L, TimeUnit.MINUTES)}
 220      *
 221      * @param sourceDuration the time duration in the given {@code sourceUnit}
 222      * @param sourceUnit the unit of the {@code sourceDuration} argument
 223      * @return the converted duration in this unit,
 224      * or {@code Long.MIN_VALUE} if conversion would negatively
 225      * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
 226      */
 227     public long convert(long sourceDuration, TimeUnit sourceUnit) {
 228         throw new AbstractMethodError();
 229     }
 230 
 231     /**
 232      * Equivalent to
 233      * {@link #convert(long, TimeUnit) NANOSECONDS.convert(duration, this)}.
 234      * @param duration the duration
 235      * @return the converted duration,
 236      * or {@code Long.MIN_VALUE} if conversion would negatively
 237      * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
 238      */
 239     public long toNanos(long duration) {
 240         throw new AbstractMethodError();
 241     }
 242 
 243     /**
 244      * Equivalent to
 245      * {@link #convert(long, TimeUnit) MICROSECONDS.convert(duration, this)}.
 246      * @param duration the duration
 247      * @return the converted duration,
 248      * or {@code Long.MIN_VALUE} if conversion would negatively
 249      * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
 250      */
 251     public long toMicros(long duration) {
 252         throw new AbstractMethodError();
 253     }
 254 
 255     /**
 256      * Equivalent to
 257      * {@link #convert(long, TimeUnit) MILLISECONDS.convert(duration, this)}.
 258      * @param duration the duration
 259      * @return the converted duration,
 260      * or {@code Long.MIN_VALUE} if conversion would negatively
 261      * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
 262      */
 263     public long toMillis(long duration) {
 264         throw new AbstractMethodError();
 265     }
 266 
 267     /**
 268      * Equivalent to
 269      * {@link #convert(long, TimeUnit) SECONDS.convert(duration, this)}.
 270      * @param duration the duration
 271      * @return the converted duration,
 272      * or {@code Long.MIN_VALUE} if conversion would negatively
 273      * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
 274      */
 275     public long toSeconds(long duration) {
 276         throw new AbstractMethodError();
 277     }
 278 
 279     /**
 280      * Equivalent to
 281      * {@link #convert(long, TimeUnit) MINUTES.convert(duration, this)}.
 282      * @param duration the duration
 283      * @return the converted duration,
 284      * or {@code Long.MIN_VALUE} if conversion would negatively
 285      * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
 286      * @since 1.6
 287      */
 288     public long toMinutes(long duration) {
 289         throw new AbstractMethodError();
 290     }
 291 
 292     /**
 293      * Equivalent to
 294      * {@link #convert(long, TimeUnit) HOURS.convert(duration, this)}.
 295      * @param duration the duration
 296      * @return the converted duration,
 297      * or {@code Long.MIN_VALUE} if conversion would negatively
 298      * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
 299      * @since 1.6
 300      */
 301     public long toHours(long duration) {
 302         throw new AbstractMethodError();
 303     }
 304 
 305     /**
 306      * Equivalent to
 307      * {@link #convert(long, TimeUnit) DAYS.convert(duration, this)}.
 308      * @param duration the duration
 309      * @return the converted duration
 310      * @since 1.6
 311      */
 312     public long toDays(long duration) {
 313         throw new AbstractMethodError();
 314     }
 315 
 316     /**
 317      * Utility to compute the excess-nanosecond argument to wait,
 318      * sleep, join.
 319      * @param d the duration
 320      * @param m the number of milliseconds
 321      * @return the number of nanoseconds
 322      */
 323     abstract int excessNanos(long d, long m);
 324 
 325     /**
 326      * Performs a timed {@link Object#wait(long, int) Object.wait}
 327      * using this time unit.
 328      * This is a convenience method that converts timeout arguments
 329      * into the form required by the {@code Object.wait} method.
 330      *
 331      * <p>For example, you could implement a blocking {@code poll}
 332      * method (see {@link BlockingQueue#poll BlockingQueue.poll})
 333      * using:
 334      *
 335      * <pre> {@code
 336      * public synchronized Object poll(long timeout, TimeUnit unit)
 337      *     throws InterruptedException {
 338      *   while (empty) {
 339      *     unit.timedWait(this, timeout);
 340      *     ...
 341      *   }
 342      * }}</pre>
 343      *
 344      * @param obj the object to wait on
 345      * @param timeout the maximum time to wait. If less than
 346      * or equal to zero, do not wait at all.
 347      * @throws InterruptedException if interrupted while waiting
 348      */
 349     public void timedWait(Object obj, long timeout)
 350             throws InterruptedException {
 351         if (timeout > 0) {
 352             long ms = toMillis(timeout);
 353             int ns = excessNanos(timeout, ms);
 354             obj.wait(ms, ns);
 355         }
 356     }
 357 
 358     /**
 359      * Performs a timed {@link Thread#join(long, int) Thread.join}
 360      * using this time unit.
 361      * This is a convenience method that converts time arguments into the
 362      * form required by the {@code Thread.join} method.
 363      *
 364      * @param thread the thread to wait for
 365      * @param timeout the maximum time to wait. If less than
 366      * or equal to zero, do not wait at all.
 367      * @throws InterruptedException if interrupted while waiting
 368      */
 369     public void timedJoin(Thread thread, long timeout)
 370             throws InterruptedException {
 371         if (timeout > 0) {
 372             long ms = toMillis(timeout);
 373             int ns = excessNanos(timeout, ms);
 374             thread.join(ms, ns);
 375         }
 376     }
 377 
 378     /**
 379      * Performs a {@link Thread#sleep(long, int) Thread.sleep} using
 380      * this time unit.
 381      * This is a convenience method that converts time arguments into the
 382      * form required by the {@code Thread.sleep} method.
 383      *
 384      * @param timeout the minimum time to sleep. If less than
 385      * or equal to zero, do not sleep at all.
 386      * @throws InterruptedException if interrupted while sleeping
 387      */
 388     public void sleep(long timeout) throws InterruptedException {
 389         if (timeout > 0) {
 390             long ms = toMillis(timeout);
 391             int ns = excessNanos(timeout, ms);
 392             Thread.sleep(ms, ns);
 393         }
 394     }
 395 
 396     /**
 397      * Converts a {@code TimeUnit} to an equivalent {@code ChronoUnit}.
 398      *
 399      * @param  timeUnit the timeUnit to convert, not null
 400      * @return the converted equivalent chronoUnit
 401      * @throws IllegalArgumentException if the unit cannot be converted
 402      * @since 9
 403      */
 404     public static ChronoUnit toChronoUnit(TimeUnit timeUnit) {
 405         Objects.requireNonNull(timeUnit, "timeUnit");
 406         switch (timeUnit) {
 407             case NANOSECONDS:
 408                 return ChronoUnit.NANOS;
 409             case MICROSECONDS:
 410                 return ChronoUnit.MICROS;
 411             case MILLISECONDS:
 412                 return ChronoUnit.MILLIS;
 413             case SECONDS:
 414                 return ChronoUnit.SECONDS;
 415             case MINUTES:
 416                 return ChronoUnit.MINUTES;
 417             case HOURS:
 418                 return ChronoUnit.HOURS;
 419             case DAYS:
 420                 return ChronoUnit.DAYS;
 421             default:
 422                 throw new IllegalArgumentException("Unknown TimeUnit");
 423         }
 424     }
 425 
 426     /**
 427      * Converts a {@code ChronoUnit} to an equivalent {@code TimeUnit}.
 428      *
 429      * @param chronoUnit  the unit to convert, not null
 430      * @return the converted equivalent timeUnit
 431      * @throws IllegalArgumentException if the unit cannot be converted
 432      * @since 9
 433      */
 434     public static TimeUnit of(ChronoUnit chronoUnit) {
 435         Objects.requireNonNull(chronoUnit, "chronoUnit");
 436         switch (chronoUnit) {
 437             case NANOS:
 438                 return TimeUnit.NANOSECONDS;
 439             case MICROS:
 440                 return TimeUnit.MICROSECONDS;
 441             case MILLIS:
 442                 return TimeUnit.MILLISECONDS;
 443             case SECONDS:
 444                 return TimeUnit.SECONDS;
 445             case MINUTES:
 446                 return TimeUnit.MINUTES;
 447             case HOURS:
 448                 return TimeUnit.HOURS;
 449             case DAYS:
 450                 return TimeUnit.DAYS;
 451             default:
 452                 throw new IllegalArgumentException("No TimeUnit equivalent for " + chronoUnit);
 453         }
 454     }
 455 
 456 }