--- a/jdk/src/java.base/share/classes/java/util/concurrent/TimeUnit.java Mon Mar 28 17:12:48 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/TimeUnit.java Mon Mar 28 08:53:39 2016 -0700
@@ -75,137 +75,94 @@
/**
* Time unit representing one thousandth of a microsecond.
*/
- NANOSECONDS {
- public long toNanos(long d) { return d; }
- public long toMicros(long d) { return d/(C1/C0); }
- public long toMillis(long d) { return d/(C2/C0); }
- public long toSeconds(long d) { return d/(C3/C0); }
- public long toMinutes(long d) { return d/(C4/C0); }
- public long toHours(long d) { return d/(C5/C0); }
- public long toDays(long d) { return d/(C6/C0); }
- public long convert(long d, TimeUnit u) { return u.toNanos(d); }
- int excessNanos(long d, long m) { return (int)(d - (m*C2)); }
- },
-
+ NANOSECONDS(TimeUnit.NANO_SCALE),
/**
* Time unit representing one thousandth of a millisecond.
*/
- MICROSECONDS {
- public long toNanos(long d) { return x(d, C1/C0, MAX/(C1/C0)); }
- public long toMicros(long d) { return d; }
- public long toMillis(long d) { return d/(C2/C1); }
- public long toSeconds(long d) { return d/(C3/C1); }
- public long toMinutes(long d) { return d/(C4/C1); }
- public long toHours(long d) { return d/(C5/C1); }
- public long toDays(long d) { return d/(C6/C1); }
- public long convert(long d, TimeUnit u) { return u.toMicros(d); }
- int excessNanos(long d, long m) { return (int)((d*C1) - (m*C2)); }
- },
-
+ MICROSECONDS(TimeUnit.MICRO_SCALE),
/**
* Time unit representing one thousandth of a second.
*/
- MILLISECONDS {
- public long toNanos(long d) { return x(d, C2/C0, MAX/(C2/C0)); }
- public long toMicros(long d) { return x(d, C2/C1, MAX/(C2/C1)); }
- public long toMillis(long d) { return d; }
- public long toSeconds(long d) { return d/(C3/C2); }
- public long toMinutes(long d) { return d/(C4/C2); }
- public long toHours(long d) { return d/(C5/C2); }
- public long toDays(long d) { return d/(C6/C2); }
- public long convert(long d, TimeUnit u) { return u.toMillis(d); }
- int excessNanos(long d, long m) { return 0; }
- },
-
+ MILLISECONDS(TimeUnit.MILLI_SCALE),
/**
* Time unit representing one second.
*/
- SECONDS {
- public long toNanos(long d) { return x(d, C3/C0, MAX/(C3/C0)); }
- public long toMicros(long d) { return x(d, C3/C1, MAX/(C3/C1)); }
- public long toMillis(long d) { return x(d, C3/C2, MAX/(C3/C2)); }
- public long toSeconds(long d) { return d; }
- public long toMinutes(long d) { return d/(C4/C3); }
- public long toHours(long d) { return d/(C5/C3); }
- public long toDays(long d) { return d/(C6/C3); }
- public long convert(long d, TimeUnit u) { return u.toSeconds(d); }
- int excessNanos(long d, long m) { return 0; }
- },
-
+ SECONDS(TimeUnit.SECOND_SCALE),
/**
* Time unit representing sixty seconds.
* @since 1.6
*/
- MINUTES {
- public long toNanos(long d) { return x(d, C4/C0, MAX/(C4/C0)); }
- public long toMicros(long d) { return x(d, C4/C1, MAX/(C4/C1)); }
- public long toMillis(long d) { return x(d, C4/C2, MAX/(C4/C2)); }
- public long toSeconds(long d) { return x(d, C4/C3, MAX/(C4/C3)); }
- public long toMinutes(long d) { return d; }
- public long toHours(long d) { return d/(C5/C4); }
- public long toDays(long d) { return d/(C6/C4); }
- public long convert(long d, TimeUnit u) { return u.toMinutes(d); }
- int excessNanos(long d, long m) { return 0; }
- },
-
+ MINUTES(TimeUnit.MINUTE_SCALE),
/**
* Time unit representing sixty minutes.
* @since 1.6
*/
- HOURS {
- public long toNanos(long d) { return x(d, C5/C0, MAX/(C5/C0)); }
- public long toMicros(long d) { return x(d, C5/C1, MAX/(C5/C1)); }
- public long toMillis(long d) { return x(d, C5/C2, MAX/(C5/C2)); }
- public long toSeconds(long d) { return x(d, C5/C3, MAX/(C5/C3)); }
- public long toMinutes(long d) { return x(d, C5/C4, MAX/(C5/C4)); }
- public long toHours(long d) { return d; }
- public long toDays(long d) { return d/(C6/C5); }
- public long convert(long d, TimeUnit u) { return u.toHours(d); }
- int excessNanos(long d, long m) { return 0; }
- },
-
+ HOURS(TimeUnit.HOUR_SCALE),
/**
* Time unit representing twenty four hours.
* @since 1.6
*/
- DAYS {
- public long toNanos(long d) { return x(d, C6/C0, MAX/(C6/C0)); }
- public long toMicros(long d) { return x(d, C6/C1, MAX/(C6/C1)); }
- public long toMillis(long d) { return x(d, C6/C2, MAX/(C6/C2)); }
- public long toSeconds(long d) { return x(d, C6/C3, MAX/(C6/C3)); }
- public long toMinutes(long d) { return x(d, C6/C4, MAX/(C6/C4)); }
- public long toHours(long d) { return x(d, C6/C5, MAX/(C6/C5)); }
- public long toDays(long d) { return d; }
- public long convert(long d, TimeUnit u) { return u.toDays(d); }
- int excessNanos(long d, long m) { return 0; }
- };
+ DAYS(TimeUnit.DAY_SCALE);
+
+ // Scales as constants
+ private static final long NANO_SCALE = 1L;
+ private static final long MICRO_SCALE = 1000L * NANO_SCALE;
+ private static final long MILLI_SCALE = 1000L * MICRO_SCALE;
+ private static final long SECOND_SCALE = 1000L * MILLI_SCALE;
+ private static final long MINUTE_SCALE = 60L * SECOND_SCALE;
+ private static final long HOUR_SCALE = 60L * MINUTE_SCALE;
+ private static final long DAY_SCALE = 24L * HOUR_SCALE;
+
+ /*
+ * Instances cache conversion ratios and saturation cutoffs for
+ * the units up through SECONDS. Other cases compute them, in
+ * method cvt.
+ */
- // Handy constants for conversion methods
- static final long C0 = 1L;
- static final long C1 = C0 * 1000L;
- static final long C2 = C1 * 1000L;
- static final long C3 = C2 * 1000L;
- static final long C4 = C3 * 60L;
- static final long C5 = C4 * 60L;
- static final long C6 = C5 * 24L;
+ private final long scale;
+ private final long maxNanos;
+ private final long maxMicros;
+ private final long maxMillis;
+ private final long maxSecs;
+ private final long microRatio;
+ private final int milliRatio; // fits in 32 bits
+ private final int secRatio; // fits in 32 bits
- static final long MAX = Long.MAX_VALUE;
+ private TimeUnit(long s) {
+ this.scale = s;
+ this.maxNanos = Long.MAX_VALUE / s;
+ long ur = (s >= MICRO_SCALE) ? (s / MICRO_SCALE) : (MICRO_SCALE / s);
+ this.microRatio = ur;
+ this.maxMicros = Long.MAX_VALUE / ur;
+ long mr = (s >= MILLI_SCALE) ? (s / MILLI_SCALE) : (MILLI_SCALE / s);
+ this.milliRatio = (int)mr;
+ this.maxMillis = Long.MAX_VALUE / mr;
+ long sr = (s >= SECOND_SCALE) ? (s / SECOND_SCALE) : (SECOND_SCALE / s);
+ this.secRatio = (int)sr;
+ this.maxSecs = Long.MAX_VALUE / sr;
+ }
/**
- * Scale d by m, checking for overflow.
- * This has a short name to make above code more readable.
+ * General conversion utility.
+ *
+ * @param d duration
+ * @param dst result unit scale
+ * @param src source unit scale
*/
- static long x(long d, long m, long over) {
- if (d > +over) return Long.MAX_VALUE;
- if (d < -over) return Long.MIN_VALUE;
- return d * m;
+ private static long cvt(long d, long dst, long src) {
+ long r, m;
+ if (src == dst)
+ return d;
+ else if (src < dst)
+ return d / (dst / src);
+ else if (d > (m = Long.MAX_VALUE / (r = src / dst)))
+ return Long.MAX_VALUE;
+ else if (d < -m)
+ return Long.MIN_VALUE;
+ else
+ return d * r;
}
- // To maintain full signature compatibility with 1.5, and to improve the
- // clarity of the generated javadoc (see 6287639: Abstract methods in
- // enum classes should not be listed as abstract), method convert
- // etc. are not declared abstract but otherwise act as abstract methods.
-
/**
* Converts the given time duration in the given unit to this unit.
* Conversions from finer to coarser granularities truncate, so
@@ -221,11 +178,17 @@
* @param sourceDuration the time duration in the given {@code sourceUnit}
* @param sourceUnit the unit of the {@code sourceDuration} argument
* @return the converted duration in this unit,
- * or {@code Long.MIN_VALUE} if conversion would negatively
- * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
+ * or {@code Long.MIN_VALUE} if conversion would negatively overflow,
+ * or {@code Long.MAX_VALUE} if it would positively overflow.
*/
public long convert(long sourceDuration, TimeUnit sourceUnit) {
- throw new AbstractMethodError();
+ switch (this) {
+ case NANOSECONDS: return sourceUnit.toNanos(sourceDuration);
+ case MICROSECONDS: return sourceUnit.toMicros(sourceDuration);
+ case MILLISECONDS: return sourceUnit.toMillis(sourceDuration);
+ case SECONDS: return sourceUnit.toSeconds(sourceDuration);
+ default: return cvt(sourceDuration, scale, sourceUnit.scale);
+ }
}
/**
@@ -233,11 +196,19 @@
* {@link #convert(long, TimeUnit) NANOSECONDS.convert(duration, this)}.
* @param duration the duration
* @return the converted duration,
- * or {@code Long.MIN_VALUE} if conversion would negatively
- * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
+ * or {@code Long.MIN_VALUE} if conversion would negatively overflow,
+ * or {@code Long.MAX_VALUE} if it would positively overflow.
*/
public long toNanos(long duration) {
- throw new AbstractMethodError();
+ long s, m;
+ if ((s = scale) == NANO_SCALE)
+ return duration;
+ else if (duration > (m = maxNanos))
+ return Long.MAX_VALUE;
+ else if (duration < -m)
+ return Long.MIN_VALUE;
+ else
+ return duration * s;
}
/**
@@ -245,11 +216,21 @@
* {@link #convert(long, TimeUnit) MICROSECONDS.convert(duration, this)}.
* @param duration the duration
* @return the converted duration,
- * or {@code Long.MIN_VALUE} if conversion would negatively
- * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
+ * or {@code Long.MIN_VALUE} if conversion would negatively overflow,
+ * or {@code Long.MAX_VALUE} if it would positively overflow.
*/
public long toMicros(long duration) {
- throw new AbstractMethodError();
+ long s, m;
+ if ((s = scale) == MICRO_SCALE)
+ return duration;
+ else if (s < MICRO_SCALE)
+ return duration / microRatio;
+ else if (duration > (m = maxMicros))
+ return Long.MAX_VALUE;
+ else if (duration < -m)
+ return Long.MIN_VALUE;
+ else
+ return duration * microRatio;
}
/**
@@ -257,11 +238,21 @@
* {@link #convert(long, TimeUnit) MILLISECONDS.convert(duration, this)}.
* @param duration the duration
* @return the converted duration,
- * or {@code Long.MIN_VALUE} if conversion would negatively
- * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
+ * or {@code Long.MIN_VALUE} if conversion would negatively overflow,
+ * or {@code Long.MAX_VALUE} if it would positively overflow.
*/
public long toMillis(long duration) {
- throw new AbstractMethodError();
+ long s, m;
+ if ((s = scale) == MILLI_SCALE)
+ return duration;
+ else if (s < MILLI_SCALE)
+ return duration / milliRatio;
+ else if (duration > (m = maxMillis))
+ return Long.MAX_VALUE;
+ else if (duration < -m)
+ return Long.MIN_VALUE;
+ else
+ return duration * milliRatio;
}
/**
@@ -269,11 +260,21 @@
* {@link #convert(long, TimeUnit) SECONDS.convert(duration, this)}.
* @param duration the duration
* @return the converted duration,
- * or {@code Long.MIN_VALUE} if conversion would negatively
- * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
+ * or {@code Long.MIN_VALUE} if conversion would negatively overflow,
+ * or {@code Long.MAX_VALUE} if it would positively overflow.
*/
public long toSeconds(long duration) {
- throw new AbstractMethodError();
+ long s, m;
+ if ((s = scale) == SECOND_SCALE)
+ return duration;
+ else if (s < SECOND_SCALE)
+ return duration / secRatio;
+ else if (duration > (m = maxSecs))
+ return Long.MAX_VALUE;
+ else if (duration < -m)
+ return Long.MIN_VALUE;
+ else
+ return duration * secRatio;
}
/**
@@ -281,12 +282,12 @@
* {@link #convert(long, TimeUnit) MINUTES.convert(duration, this)}.
* @param duration the duration
* @return the converted duration,
- * or {@code Long.MIN_VALUE} if conversion would negatively
- * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
+ * or {@code Long.MIN_VALUE} if conversion would negatively overflow,
+ * or {@code Long.MAX_VALUE} if it would positively overflow.
* @since 1.6
*/
public long toMinutes(long duration) {
- throw new AbstractMethodError();
+ return cvt(duration, MINUTE_SCALE, scale);
}
/**
@@ -294,12 +295,12 @@
* {@link #convert(long, TimeUnit) HOURS.convert(duration, this)}.
* @param duration the duration
* @return the converted duration,
- * or {@code Long.MIN_VALUE} if conversion would negatively
- * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
+ * or {@code Long.MIN_VALUE} if conversion would negatively overflow,
+ * or {@code Long.MAX_VALUE} if it would positively overflow.
* @since 1.6
*/
public long toHours(long duration) {
- throw new AbstractMethodError();
+ return cvt(duration, HOUR_SCALE, scale);
}
/**
@@ -310,7 +311,7 @@
* @since 1.6
*/
public long toDays(long duration) {
- throw new AbstractMethodError();
+ return cvt(duration, DAY_SCALE, scale);
}
/**
@@ -320,7 +321,15 @@
* @param m the number of milliseconds
* @return the number of nanoseconds
*/
- abstract int excessNanos(long d, long m);
+ private int excessNanos(long d, long m) {
+ long s;
+ if ((s = scale) == NANO_SCALE)
+ return (int)(d - (m * MILLI_SCALE));
+ else if (s == MICRO_SCALE)
+ return (int)((d * 1000L) - (m * MILLI_SCALE));
+ else
+ return 0;
+ }
/**
* Performs a timed {@link Object#wait(long, int) Object.wait}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/tck/TimeUnit8Test.java Mon Mar 28 08:53:39 2016 -0700
@@ -0,0 +1,103 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea and Martin Buchholz with assistance from
+ * members of JCP JSR-166 Expert Group and released to the public
+ * domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+import static java.util.concurrent.TimeUnit.DAYS;
+import static java.util.concurrent.TimeUnit.HOURS;
+import static java.util.concurrent.TimeUnit.MICROSECONDS;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.TimeUnit.MINUTES;
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+import java.time.temporal.ChronoUnit;
+import java.util.concurrent.TimeUnit;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class TimeUnit8Test extends JSR166TestCase {
+ public static void main(String[] args) {
+ main(suite(), args);
+ }
+
+ public static Test suite() {
+ return new TestSuite(TimeUnit8Test.class);
+ }
+
+ /**
+ * tests for toChronoUnit.
+ */
+ public void testToChronoUnit() throws Exception {
+ assertSame(ChronoUnit.NANOS, NANOSECONDS.toChronoUnit());
+ assertSame(ChronoUnit.MICROS, MICROSECONDS.toChronoUnit());
+ assertSame(ChronoUnit.MILLIS, MILLISECONDS.toChronoUnit());
+ assertSame(ChronoUnit.SECONDS, SECONDS.toChronoUnit());
+ assertSame(ChronoUnit.MINUTES, MINUTES.toChronoUnit());
+ assertSame(ChronoUnit.HOURS, HOURS.toChronoUnit());
+ assertSame(ChronoUnit.DAYS, DAYS.toChronoUnit());
+
+ // Every TimeUnit has a defined ChronoUnit equivalent
+ for (TimeUnit x : TimeUnit.values())
+ assertSame(x, TimeUnit.of(x.toChronoUnit()));
+ }
+
+ /**
+ * tests for TimeUnit.of(ChronoUnit).
+ */
+ public void testTimeUnitOf() throws Exception {
+ assertSame(NANOSECONDS, TimeUnit.of(ChronoUnit.NANOS));
+ assertSame(MICROSECONDS, TimeUnit.of(ChronoUnit.MICROS));
+ assertSame(MILLISECONDS, TimeUnit.of(ChronoUnit.MILLIS));
+ assertSame(SECONDS, TimeUnit.of(ChronoUnit.SECONDS));
+ assertSame(MINUTES, TimeUnit.of(ChronoUnit.MINUTES));
+ assertSame(HOURS, TimeUnit.of(ChronoUnit.HOURS));
+ assertSame(DAYS, TimeUnit.of(ChronoUnit.DAYS));
+
+ assertThrows(NullPointerException.class,
+ () -> TimeUnit.of((ChronoUnit)null));
+
+ // ChronoUnits either round trip to their TimeUnit
+ // equivalents, or throw IllegalArgumentException.
+ for (ChronoUnit cu : ChronoUnit.values()) {
+ final TimeUnit tu;
+ try {
+ tu = TimeUnit.of(cu);
+ } catch (IllegalArgumentException acceptable) {
+ continue;
+ }
+ assertSame(cu, tu.toChronoUnit());
+ }
+ }
+
+}
--- a/jdk/test/java/util/concurrent/tck/TimeUnitTest.java Mon Mar 28 17:12:48 2016 +0300
+++ b/jdk/test/java/util/concurrent/tck/TimeUnitTest.java Mon Mar 28 08:53:39 2016 -0700
@@ -41,7 +41,6 @@
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
-import java.time.temporal.ChronoUnit;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -124,6 +123,15 @@
assertEquals(t,
NANOSECONDS.convert(t, NANOSECONDS));
}
+
+ for (TimeUnit x : TimeUnit.values()) {
+ long[] zs = {
+ 0, 1, -1,
+ Integer.MAX_VALUE, Integer.MIN_VALUE,
+ Long.MAX_VALUE, Long.MIN_VALUE,
+ };
+ for (long z : zs) assertEquals(z, x.convert(z, x));
+ }
}
/**
@@ -308,6 +316,27 @@
NANOSECONDS.convert(Long.MAX_VALUE / 2, DAYS));
assertEquals(Long.MIN_VALUE,
NANOSECONDS.convert(-Long.MAX_VALUE / 4, DAYS));
+
+ for (TimeUnit x : TimeUnit.values())
+ for (TimeUnit y : TimeUnit.values()) {
+ long ratio = x.toNanos(1) / y.toNanos(1);
+ if (ratio >= 1) {
+ assertEquals(ratio, y.convert(1, x));
+ assertEquals(1, x.convert(ratio, y));
+ long max = Long.MAX_VALUE/ratio;
+ assertEquals(max * ratio, y.convert(max, x));
+ assertEquals(-max * ratio, y.convert(-max, x));
+ assertEquals(max, x.convert(max * ratio, y));
+ assertEquals(-max, x.convert(-max * ratio, y));
+ if (max < Long.MAX_VALUE) {
+ assertEquals(Long.MAX_VALUE, y.convert(max + 1, x));
+ assertEquals(Long.MIN_VALUE, y.convert(-max - 1, x));
+ assertEquals(Long.MIN_VALUE, y.convert(Long.MIN_VALUE + 1, x));
+ }
+ assertEquals(Long.MAX_VALUE, y.convert(Long.MAX_VALUE, x));
+ assertEquals(Long.MIN_VALUE, y.convert(Long.MIN_VALUE, x));
+ }
+ }
}
/**
@@ -319,6 +348,146 @@
MILLISECONDS.toNanos(Long.MAX_VALUE / 2));
assertEquals(Long.MIN_VALUE,
MILLISECONDS.toNanos(-Long.MAX_VALUE / 3));
+
+ for (TimeUnit x : TimeUnit.values()) {
+ long ratio = x.toNanos(1) / NANOSECONDS.toNanos(1);
+ if (ratio >= 1) {
+ long max = Long.MAX_VALUE/ratio;
+ for (long z : new long[] {0, 1, -1, max, -max})
+ assertEquals(z * ratio, x.toNanos(z));
+ if (max < Long.MAX_VALUE) {
+ assertEquals(Long.MAX_VALUE, x.toNanos(max + 1));
+ assertEquals(Long.MIN_VALUE, x.toNanos(-max - 1));
+ assertEquals(Long.MIN_VALUE, x.toNanos(Long.MIN_VALUE + 1));
+ }
+ assertEquals(Long.MAX_VALUE, x.toNanos(Long.MAX_VALUE));
+ assertEquals(Long.MIN_VALUE, x.toNanos(Long.MIN_VALUE));
+ if (max < Integer.MAX_VALUE) {
+ assertEquals(Long.MAX_VALUE, x.toNanos(Integer.MAX_VALUE));
+ assertEquals(Long.MIN_VALUE, x.toNanos(Integer.MIN_VALUE));
+ }
+ }
+ }
+ }
+
+ /**
+ * toMicros saturates positive too-large values to Long.MAX_VALUE
+ * and negative to LONG.MIN_VALUE
+ */
+ public void testToMicrosSaturate() {
+ for (TimeUnit x : TimeUnit.values()) {
+ long ratio = x.toNanos(1) / MICROSECONDS.toNanos(1);
+ if (ratio >= 1) {
+ long max = Long.MAX_VALUE/ratio;
+ for (long z : new long[] {0, 1, -1, max, -max})
+ assertEquals(z * ratio, x.toMicros(z));
+ if (max < Long.MAX_VALUE) {
+ assertEquals(Long.MAX_VALUE, x.toMicros(max + 1));
+ assertEquals(Long.MIN_VALUE, x.toMicros(-max - 1));
+ assertEquals(Long.MIN_VALUE, x.toMicros(Long.MIN_VALUE + 1));
+ }
+ assertEquals(Long.MAX_VALUE, x.toMicros(Long.MAX_VALUE));
+ assertEquals(Long.MIN_VALUE, x.toMicros(Long.MIN_VALUE));
+ if (max < Integer.MAX_VALUE) {
+ assertEquals(Long.MAX_VALUE, x.toMicros(Integer.MAX_VALUE));
+ assertEquals(Long.MIN_VALUE, x.toMicros(Integer.MIN_VALUE));
+ }
+ }
+ }
+ }
+
+ /**
+ * toMillis saturates positive too-large values to Long.MAX_VALUE
+ * and negative to LONG.MIN_VALUE
+ */
+ public void testToMillisSaturate() {
+ for (TimeUnit x : TimeUnit.values()) {
+ long ratio = x.toNanos(1) / MILLISECONDS.toNanos(1);
+ if (ratio >= 1) {
+ long max = Long.MAX_VALUE/ratio;
+ for (long z : new long[] {0, 1, -1, max, -max})
+ assertEquals(z * ratio, x.toMillis(z));
+ if (max < Long.MAX_VALUE) {
+ assertEquals(Long.MAX_VALUE, x.toMillis(max + 1));
+ assertEquals(Long.MIN_VALUE, x.toMillis(-max - 1));
+ assertEquals(Long.MIN_VALUE, x.toMillis(Long.MIN_VALUE + 1));
+ }
+ assertEquals(Long.MAX_VALUE, x.toMillis(Long.MAX_VALUE));
+ assertEquals(Long.MIN_VALUE, x.toMillis(Long.MIN_VALUE));
+ if (max < Integer.MAX_VALUE) {
+ assertEquals(Long.MAX_VALUE, x.toMillis(Integer.MAX_VALUE));
+ assertEquals(Long.MIN_VALUE, x.toMillis(Integer.MIN_VALUE));
+ }
+ }
+ }
+ }
+
+ /**
+ * toSeconds saturates positive too-large values to Long.MAX_VALUE
+ * and negative to LONG.MIN_VALUE
+ */
+ public void testToSecondsSaturate() {
+ for (TimeUnit x : TimeUnit.values()) {
+ long ratio = x.toNanos(1) / SECONDS.toNanos(1);
+ if (ratio >= 1) {
+ long max = Long.MAX_VALUE/ratio;
+ for (long z : new long[] {0, 1, -1, max, -max})
+ assertEquals(z * ratio, x.toSeconds(z));
+ if (max < Long.MAX_VALUE) {
+ assertEquals(Long.MAX_VALUE, x.toSeconds(max + 1));
+ assertEquals(Long.MIN_VALUE, x.toSeconds(-max - 1));
+ assertEquals(Long.MIN_VALUE, x.toSeconds(Long.MIN_VALUE + 1));
+ }
+ assertEquals(Long.MAX_VALUE, x.toSeconds(Long.MAX_VALUE));
+ assertEquals(Long.MIN_VALUE, x.toSeconds(Long.MIN_VALUE));
+ if (max < Integer.MAX_VALUE) {
+ assertEquals(Long.MAX_VALUE, x.toSeconds(Integer.MAX_VALUE));
+ assertEquals(Long.MIN_VALUE, x.toSeconds(Integer.MIN_VALUE));
+ }
+ }
+ }
+ }
+
+ /**
+ * toMinutes saturates positive too-large values to Long.MAX_VALUE
+ * and negative to LONG.MIN_VALUE
+ */
+ public void testToMinutesSaturate() {
+ for (TimeUnit x : TimeUnit.values()) {
+ long ratio = x.toNanos(1) / MINUTES.toNanos(1);
+ if (ratio > 1) {
+ long max = Long.MAX_VALUE/ratio;
+ for (long z : new long[] {0, 1, -1, max, -max})
+ assertEquals(z * ratio, x.toMinutes(z));
+ assertEquals(Long.MAX_VALUE, x.toMinutes(max + 1));
+ assertEquals(Long.MIN_VALUE, x.toMinutes(-max - 1));
+ assertEquals(Long.MAX_VALUE, x.toMinutes(Long.MAX_VALUE));
+ assertEquals(Long.MIN_VALUE, x.toMinutes(Long.MIN_VALUE));
+ assertEquals(Long.MIN_VALUE, x.toMinutes(Long.MIN_VALUE + 1));
+ }
+ }
+ }
+
+ /**
+ * toHours saturates positive too-large values to Long.MAX_VALUE
+ * and negative to LONG.MIN_VALUE
+ */
+ public void testToHoursSaturate() {
+ for (TimeUnit x : TimeUnit.values()) {
+ long ratio = x.toNanos(1) / HOURS.toNanos(1);
+ if (ratio >= 1) {
+ long max = Long.MAX_VALUE/ratio;
+ for (long z : new long[] {0, 1, -1, max, -max})
+ assertEquals(z * ratio, x.toHours(z));
+ if (max < Long.MAX_VALUE) {
+ assertEquals(Long.MAX_VALUE, x.toHours(max + 1));
+ assertEquals(Long.MIN_VALUE, x.toHours(-max - 1));
+ assertEquals(Long.MIN_VALUE, x.toHours(Long.MIN_VALUE + 1));
+ }
+ assertEquals(Long.MAX_VALUE, x.toHours(Long.MAX_VALUE));
+ assertEquals(Long.MIN_VALUE, x.toHours(Long.MIN_VALUE));
+ }
+ }
}
/**
@@ -461,49 +630,4 @@
assertSame(x, serialClone(x));
}
- /**
- * tests for toChronoUnit.
- */
- public void testToChronoUnit() throws Exception {
- assertSame(ChronoUnit.NANOS, NANOSECONDS.toChronoUnit());
- assertSame(ChronoUnit.MICROS, MICROSECONDS.toChronoUnit());
- assertSame(ChronoUnit.MILLIS, MILLISECONDS.toChronoUnit());
- assertSame(ChronoUnit.SECONDS, SECONDS.toChronoUnit());
- assertSame(ChronoUnit.MINUTES, MINUTES.toChronoUnit());
- assertSame(ChronoUnit.HOURS, HOURS.toChronoUnit());
- assertSame(ChronoUnit.DAYS, DAYS.toChronoUnit());
-
- // Every TimeUnit has a defined ChronoUnit equivalent
- for (TimeUnit x : TimeUnit.values())
- assertSame(x, TimeUnit.of(x.toChronoUnit()));
- }
-
- /**
- * tests for TimeUnit.of(ChronoUnit).
- */
- public void testTimeUnitOf() throws Exception {
- assertSame(NANOSECONDS, TimeUnit.of(ChronoUnit.NANOS));
- assertSame(MICROSECONDS, TimeUnit.of(ChronoUnit.MICROS));
- assertSame(MILLISECONDS, TimeUnit.of(ChronoUnit.MILLIS));
- assertSame(SECONDS, TimeUnit.of(ChronoUnit.SECONDS));
- assertSame(MINUTES, TimeUnit.of(ChronoUnit.MINUTES));
- assertSame(HOURS, TimeUnit.of(ChronoUnit.HOURS));
- assertSame(DAYS, TimeUnit.of(ChronoUnit.DAYS));
-
- assertThrows(NullPointerException.class,
- () -> TimeUnit.of((ChronoUnit)null));
-
- // ChronoUnits either round trip to their TimeUnit
- // equivalents, or throw IllegalArgumentException.
- for (ChronoUnit cu : ChronoUnit.values()) {
- final TimeUnit tu;
- try {
- tu = TimeUnit.of(cu);
- } catch (IllegalArgumentException acceptable) {
- continue;
- }
- assertSame(cu, tu.toChronoUnit());
- }
- }
-
}