• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Written by Doug Lea with assistance from members of JCP JSR-166
3  * Expert Group and released to the public domain, as explained at
4  * http://creativecommons.org/publicdomain/zero/1.0/
5  */
6 
7 package java.util.concurrent;
8 
9 import java.util.Objects;
10 
11 // BEGIN android-note
12 // removed java 9 ChronoUnit related code
13 // END android-note
14 
15 /**
16  * A {@code TimeUnit} represents time durations at a given unit of
17  * granularity and provides utility methods to convert across units,
18  * and to perform timing and delay operations in these units.  A
19  * {@code TimeUnit} does not maintain time information, but only
20  * helps organize and use time representations that may be maintained
21  * separately across various contexts.  A nanosecond is defined as one
22  * thousandth of a microsecond, a microsecond as one thousandth of a
23  * millisecond, a millisecond as one thousandth of a second, a minute
24  * as sixty seconds, an hour as sixty minutes, and a day as twenty four
25  * hours.
26  *
27  * <p>A {@code TimeUnit} is mainly used to inform time-based methods
28  * how a given timing parameter should be interpreted. For example,
29  * the following code will timeout in 50 milliseconds if the {@link
30  * java.util.concurrent.locks.Lock lock} is not available:
31  *
32  * <pre> {@code
33  * Lock lock = ...;
34  * if (lock.tryLock(50L, TimeUnit.MILLISECONDS)) ...}</pre>
35  *
36  * while this code will timeout in 50 seconds:
37  * <pre> {@code
38  * Lock lock = ...;
39  * if (lock.tryLock(50L, TimeUnit.SECONDS)) ...}</pre>
40  *
41  * Note however, that there is no guarantee that a particular timeout
42  * implementation will be able to notice the passage of time at the
43  * same granularity as the given {@code TimeUnit}.
44  *
45  * @since 1.5
46  * @author Doug Lea
47  */
48 public enum TimeUnit {
49     /**
50      * Time unit representing one thousandth of a microsecond.
51      */
52     NANOSECONDS {
toNanos(long d)53         public long toNanos(long d)   { return d; }
toMicros(long d)54         public long toMicros(long d)  { return d/(C1/C0); }
toMillis(long d)55         public long toMillis(long d)  { return d/(C2/C0); }
toSeconds(long d)56         public long toSeconds(long d) { return d/(C3/C0); }
toMinutes(long d)57         public long toMinutes(long d) { return d/(C4/C0); }
toHours(long d)58         public long toHours(long d)   { return d/(C5/C0); }
toDays(long d)59         public long toDays(long d)    { return d/(C6/C0); }
convert(long d, TimeUnit u)60         public long convert(long d, TimeUnit u) { return u.toNanos(d); }
excessNanos(long d, long m)61         int excessNanos(long d, long m) { return (int)(d - (m*C2)); }
62     },
63 
64     /**
65      * Time unit representing one thousandth of a millisecond.
66      */
67     MICROSECONDS {
toNanos(long d)68         public long toNanos(long d)   { return x(d, C1/C0, MAX/(C1/C0)); }
toMicros(long d)69         public long toMicros(long d)  { return d; }
toMillis(long d)70         public long toMillis(long d)  { return d/(C2/C1); }
toSeconds(long d)71         public long toSeconds(long d) { return d/(C3/C1); }
toMinutes(long d)72         public long toMinutes(long d) { return d/(C4/C1); }
toHours(long d)73         public long toHours(long d)   { return d/(C5/C1); }
toDays(long d)74         public long toDays(long d)    { return d/(C6/C1); }
convert(long d, TimeUnit u)75         public long convert(long d, TimeUnit u) { return u.toMicros(d); }
excessNanos(long d, long m)76         int excessNanos(long d, long m) { return (int)((d*C1) - (m*C2)); }
77     },
78 
79     /**
80      * Time unit representing one thousandth of a second.
81      */
82     MILLISECONDS {
toNanos(long d)83         public long toNanos(long d)   { return x(d, C2/C0, MAX/(C2/C0)); }
toMicros(long d)84         public long toMicros(long d)  { return x(d, C2/C1, MAX/(C2/C1)); }
toMillis(long d)85         public long toMillis(long d)  { return d; }
toSeconds(long d)86         public long toSeconds(long d) { return d/(C3/C2); }
toMinutes(long d)87         public long toMinutes(long d) { return d/(C4/C2); }
toHours(long d)88         public long toHours(long d)   { return d/(C5/C2); }
toDays(long d)89         public long toDays(long d)    { return d/(C6/C2); }
convert(long d, TimeUnit u)90         public long convert(long d, TimeUnit u) { return u.toMillis(d); }
excessNanos(long d, long m)91         int excessNanos(long d, long m) { return 0; }
92     },
93 
94     /**
95      * Time unit representing one second.
96      */
97     SECONDS {
toNanos(long d)98         public long toNanos(long d)   { return x(d, C3/C0, MAX/(C3/C0)); }
toMicros(long d)99         public long toMicros(long d)  { return x(d, C3/C1, MAX/(C3/C1)); }
toMillis(long d)100         public long toMillis(long d)  { return x(d, C3/C2, MAX/(C3/C2)); }
toSeconds(long d)101         public long toSeconds(long d) { return d; }
toMinutes(long d)102         public long toMinutes(long d) { return d/(C4/C3); }
toHours(long d)103         public long toHours(long d)   { return d/(C5/C3); }
toDays(long d)104         public long toDays(long d)    { return d/(C6/C3); }
convert(long d, TimeUnit u)105         public long convert(long d, TimeUnit u) { return u.toSeconds(d); }
excessNanos(long d, long m)106         int excessNanos(long d, long m) { return 0; }
107     },
108 
109     /**
110      * Time unit representing sixty seconds.
111      * @since 1.6
112      */
113     MINUTES {
toNanos(long d)114         public long toNanos(long d)   { return x(d, C4/C0, MAX/(C4/C0)); }
toMicros(long d)115         public long toMicros(long d)  { return x(d, C4/C1, MAX/(C4/C1)); }
toMillis(long d)116         public long toMillis(long d)  { return x(d, C4/C2, MAX/(C4/C2)); }
toSeconds(long d)117         public long toSeconds(long d) { return x(d, C4/C3, MAX/(C4/C3)); }
toMinutes(long d)118         public long toMinutes(long d) { return d; }
toHours(long d)119         public long toHours(long d)   { return d/(C5/C4); }
toDays(long d)120         public long toDays(long d)    { return d/(C6/C4); }
convert(long d, TimeUnit u)121         public long convert(long d, TimeUnit u) { return u.toMinutes(d); }
excessNanos(long d, long m)122         int excessNanos(long d, long m) { return 0; }
123     },
124 
125     /**
126      * Time unit representing sixty minutes.
127      * @since 1.6
128      */
129     HOURS {
toNanos(long d)130         public long toNanos(long d)   { return x(d, C5/C0, MAX/(C5/C0)); }
toMicros(long d)131         public long toMicros(long d)  { return x(d, C5/C1, MAX/(C5/C1)); }
toMillis(long d)132         public long toMillis(long d)  { return x(d, C5/C2, MAX/(C5/C2)); }
toSeconds(long d)133         public long toSeconds(long d) { return x(d, C5/C3, MAX/(C5/C3)); }
toMinutes(long d)134         public long toMinutes(long d) { return x(d, C5/C4, MAX/(C5/C4)); }
toHours(long d)135         public long toHours(long d)   { return d; }
toDays(long d)136         public long toDays(long d)    { return d/(C6/C5); }
convert(long d, TimeUnit u)137         public long convert(long d, TimeUnit u) { return u.toHours(d); }
excessNanos(long d, long m)138         int excessNanos(long d, long m) { return 0; }
139     },
140 
141     /**
142      * Time unit representing twenty four hours.
143      * @since 1.6
144      */
145     DAYS {
toNanos(long d)146         public long toNanos(long d)   { return x(d, C6/C0, MAX/(C6/C0)); }
toMicros(long d)147         public long toMicros(long d)  { return x(d, C6/C1, MAX/(C6/C1)); }
toMillis(long d)148         public long toMillis(long d)  { return x(d, C6/C2, MAX/(C6/C2)); }
toSeconds(long d)149         public long toSeconds(long d) { return x(d, C6/C3, MAX/(C6/C3)); }
toMinutes(long d)150         public long toMinutes(long d) { return x(d, C6/C4, MAX/(C6/C4)); }
toHours(long d)151         public long toHours(long d)   { return x(d, C6/C5, MAX/(C6/C5)); }
toDays(long d)152         public long toDays(long d)    { return d; }
convert(long d, TimeUnit u)153         public long convert(long d, TimeUnit u) { return u.toDays(d); }
excessNanos(long d, long m)154         int excessNanos(long d, long m) { return 0; }
155     };
156 
157     // Handy constants for conversion methods
158     static final long C0 = 1L;
159     static final long C1 = C0 * 1000L;
160     static final long C2 = C1 * 1000L;
161     static final long C3 = C2 * 1000L;
162     static final long C4 = C3 * 60L;
163     static final long C5 = C4 * 60L;
164     static final long C6 = C5 * 24L;
165 
166     static final long MAX = Long.MAX_VALUE;
167 
168     /**
169      * Scale d by m, checking for overflow.
170      * This has a short name to make above code more readable.
171      */
x(long d, long m, long over)172     static long x(long d, long m, long over) {
173         if (d > +over) return Long.MAX_VALUE;
174         if (d < -over) return Long.MIN_VALUE;
175         return d * m;
176     }
177 
178     // To maintain full signature compatibility with 1.5, and to improve the
179     // clarity of the generated javadoc (see 6287639: Abstract methods in
180     // enum classes should not be listed as abstract), method convert
181     // etc. are not declared abstract but otherwise act as abstract methods.
182 
183     /**
184      * Converts the given time duration in the given unit to this unit.
185      * Conversions from finer to coarser granularities truncate, so
186      * lose precision. For example, converting {@code 999} milliseconds
187      * to seconds results in {@code 0}. Conversions from coarser to
188      * finer granularities with arguments that would numerically
189      * overflow saturate to {@code Long.MIN_VALUE} if negative or
190      * {@code Long.MAX_VALUE} if positive.
191      *
192      * <p>For example, to convert 10 minutes to milliseconds, use:
193      * {@code TimeUnit.MILLISECONDS.convert(10L, TimeUnit.MINUTES)}
194      *
195      * @param sourceDuration the time duration in the given {@code sourceUnit}
196      * @param sourceUnit the unit of the {@code sourceDuration} argument
197      * @return the converted duration in this unit,
198      * or {@code Long.MIN_VALUE} if conversion would negatively
199      * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
200      */
convert(long sourceDuration, TimeUnit sourceUnit)201     public long convert(long sourceDuration, TimeUnit sourceUnit) {
202         throw new AbstractMethodError();
203     }
204 
205     /**
206      * Equivalent to
207      * {@link #convert(long, TimeUnit) NANOSECONDS.convert(duration, this)}.
208      * @param duration the duration
209      * @return the converted duration,
210      * or {@code Long.MIN_VALUE} if conversion would negatively
211      * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
212      */
toNanos(long duration)213     public long toNanos(long duration) {
214         throw new AbstractMethodError();
215     }
216 
217     /**
218      * Equivalent to
219      * {@link #convert(long, TimeUnit) MICROSECONDS.convert(duration, this)}.
220      * @param duration the duration
221      * @return the converted duration,
222      * or {@code Long.MIN_VALUE} if conversion would negatively
223      * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
224      */
toMicros(long duration)225     public long toMicros(long duration) {
226         throw new AbstractMethodError();
227     }
228 
229     /**
230      * Equivalent to
231      * {@link #convert(long, TimeUnit) MILLISECONDS.convert(duration, this)}.
232      * @param duration the duration
233      * @return the converted duration,
234      * or {@code Long.MIN_VALUE} if conversion would negatively
235      * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
236      */
toMillis(long duration)237     public long toMillis(long duration) {
238         throw new AbstractMethodError();
239     }
240 
241     /**
242      * Equivalent to
243      * {@link #convert(long, TimeUnit) SECONDS.convert(duration, this)}.
244      * @param duration the duration
245      * @return the converted duration,
246      * or {@code Long.MIN_VALUE} if conversion would negatively
247      * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
248      */
toSeconds(long duration)249     public long toSeconds(long duration) {
250         throw new AbstractMethodError();
251     }
252 
253     /**
254      * Equivalent to
255      * {@link #convert(long, TimeUnit) MINUTES.convert(duration, this)}.
256      * @param duration the duration
257      * @return the converted duration,
258      * or {@code Long.MIN_VALUE} if conversion would negatively
259      * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
260      * @since 1.6
261      */
toMinutes(long duration)262     public long toMinutes(long duration) {
263         throw new AbstractMethodError();
264     }
265 
266     /**
267      * Equivalent to
268      * {@link #convert(long, TimeUnit) HOURS.convert(duration, this)}.
269      * @param duration the duration
270      * @return the converted duration,
271      * or {@code Long.MIN_VALUE} if conversion would negatively
272      * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
273      * @since 1.6
274      */
toHours(long duration)275     public long toHours(long duration) {
276         throw new AbstractMethodError();
277     }
278 
279     /**
280      * Equivalent to
281      * {@link #convert(long, TimeUnit) DAYS.convert(duration, this)}.
282      * @param duration the duration
283      * @return the converted duration
284      * @since 1.6
285      */
toDays(long duration)286     public long toDays(long duration) {
287         throw new AbstractMethodError();
288     }
289 
290     /**
291      * Utility to compute the excess-nanosecond argument to wait,
292      * sleep, join.
293      * @param d the duration
294      * @param m the number of milliseconds
295      * @return the number of nanoseconds
296      */
excessNanos(long d, long m)297     abstract int excessNanos(long d, long m);
298 
299     /**
300      * Performs a timed {@link Object#wait(long, int) Object.wait}
301      * using this time unit.
302      * This is a convenience method that converts timeout arguments
303      * into the form required by the {@code Object.wait} method.
304      *
305      * <p>For example, you could implement a blocking {@code poll}
306      * method (see {@link BlockingQueue#poll BlockingQueue.poll})
307      * using:
308      *
309      * <pre> {@code
310      * public synchronized Object poll(long timeout, TimeUnit unit)
311      *     throws InterruptedException {
312      *   while (empty) {
313      *     unit.timedWait(this, timeout);
314      *     ...
315      *   }
316      * }}</pre>
317      *
318      * @param obj the object to wait on
319      * @param timeout the maximum time to wait. If less than
320      * or equal to zero, do not wait at all.
321      * @throws InterruptedException if interrupted while waiting
322      */
timedWait(Object obj, long timeout)323     public void timedWait(Object obj, long timeout)
324             throws InterruptedException {
325         if (timeout > 0) {
326             long ms = toMillis(timeout);
327             int ns = excessNanos(timeout, ms);
328             obj.wait(ms, ns);
329         }
330     }
331 
332     /**
333      * Performs a timed {@link Thread#join(long, int) Thread.join}
334      * using this time unit.
335      * This is a convenience method that converts time arguments into the
336      * form required by the {@code Thread.join} method.
337      *
338      * @param thread the thread to wait for
339      * @param timeout the maximum time to wait. If less than
340      * or equal to zero, do not wait at all.
341      * @throws InterruptedException if interrupted while waiting
342      */
timedJoin(Thread thread, long timeout)343     public void timedJoin(Thread thread, long timeout)
344             throws InterruptedException {
345         if (timeout > 0) {
346             long ms = toMillis(timeout);
347             int ns = excessNanos(timeout, ms);
348             thread.join(ms, ns);
349         }
350     }
351 
352     /**
353      * Performs a {@link Thread#sleep(long, int) Thread.sleep} using
354      * this time unit.
355      * This is a convenience method that converts time arguments into the
356      * form required by the {@code Thread.sleep} method.
357      *
358      * @param timeout the minimum time to sleep. If less than
359      * or equal to zero, do not sleep at all.
360      * @throws InterruptedException if interrupted while sleeping
361      */
sleep(long timeout)362     public void sleep(long timeout) throws InterruptedException {
363         if (timeout > 0) {
364             long ms = toMillis(timeout);
365             int ns = excessNanos(timeout, ms);
366             Thread.sleep(ms, ns);
367         }
368     }
369 }
370