
org.apache.brooklyn.util.time.Duration Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of brooklyn-utils-common Show documentation
Show all versions of brooklyn-utils-common Show documentation
Utility classes and methods developed for Brooklyn but not dependendent on Brooklyn or much else
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.brooklyn.util.time;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
import org.apache.brooklyn.util.text.Strings;
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.base.Stopwatch;
/** simple class determines a length of time */
public class Duration implements Comparable, Serializable {
private static final long serialVersionUID = -2303909964519279617L;
public static final Duration ZERO = of(0, null);
public static final Duration ONE_MILLISECOND = of(1, TimeUnit.MILLISECONDS);
public static final Duration ONE_SECOND = of(1, TimeUnit.SECONDS);
public static final Duration FIVE_SECONDS = of(5, TimeUnit.SECONDS);
public static final Duration TEN_SECONDS = of(10, TimeUnit.SECONDS);
public static final Duration THIRTY_SECONDS = of(30, TimeUnit.SECONDS);
public static final Duration ONE_MINUTE = of(1, TimeUnit.MINUTES);
public static final Duration TWO_MINUTES = of(2, TimeUnit.MINUTES);
public static final Duration FIVE_MINUTES = of(5, TimeUnit.MINUTES);
public static final Duration ONE_HOUR = of(1, TimeUnit.HOURS);
public static final Duration ONE_DAY = of(1, TimeUnit.DAYS);
/** longest supported duration, 2^{63}-1 nanoseconds, approx ten billion seconds, or 300 years */
public static final Duration PRACTICALLY_FOREVER = of(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
private final long nanos;
public Duration(long value, TimeUnit unit) {
if (value != 0) {
Preconditions.checkNotNull(unit, "Cannot accept null timeunit (unless value is 0)");
} else {
unit = TimeUnit.MILLISECONDS;
}
nanos = TimeUnit.NANOSECONDS.convert(value, unit);
}
@Override
public int compareTo(Duration o) {
return ((Long)toNanoseconds()).compareTo(o.toNanoseconds());
}
@Override
public String toString() {
return Time.makeTimeStringExact(this);
}
public String toStringRounded() {
return Time.makeTimeStringRounded(this);
}
@Override
public boolean equals(Object o) {
if (!(o instanceof Duration)) return false;
return toMilliseconds() == ((Duration)o).toMilliseconds();
}
@Override
public int hashCode() {
return Long.valueOf(toMilliseconds()).hashCode();
}
/** converts to the given {@link TimeUnit}, using {@link TimeUnit#convert(long, TimeUnit)} which rounds _down_
* (so 1 nanosecond converted to milliseconds gives 0 milliseconds, and -1 ns gives -1 ms) */
public long toUnit(TimeUnit unit) {
return unit.convert(nanos, TimeUnit.NANOSECONDS);
}
/** as {@link #toUnit(TimeUnit)} but rounding as indicated
* (rather than always taking the floor which is TimeUnit's default behaviour) */
public long toUnit(TimeUnit unit, RoundingMode rounding) {
long result = unit.convert(nanos, TimeUnit.NANOSECONDS);
long check = TimeUnit.NANOSECONDS.convert(result, unit);
if (check==nanos || rounding==null || rounding==RoundingMode.UNNECESSARY) return result;
return new BigDecimal(nanos).divide(new BigDecimal(unit.toNanos(1)), rounding).longValue();
}
/** as {@link #toUnit(TimeUnit)} but rounding away from zero,
* so 1 ns converted to ms gives 1 ms, and -1 ns gives 1ms */
public long toUnitRoundingUp(TimeUnit unit) {
return toUnit(unit, RoundingMode.UP);
}
public long toMilliseconds() {
return toUnit(TimeUnit.MILLISECONDS);
}
/** as {@link #toMilliseconds()} but rounding away from zero (so 1 nanosecond gets rounded to 1 millisecond);
* see {@link #toUnitRoundingUp(TimeUnit)}; provided as a convenience on top of {@link #toUnit(TimeUnit, RoundingMode)}
* as this is a common case (when you want to make sure you wait at least a certain amount of time) */
public long toMillisecondsRoundingUp() {
return toUnitRoundingUp(TimeUnit.MILLISECONDS);
}
public long toNanoseconds() {
return nanos;
}
public long toSeconds() {
return toUnit(TimeUnit.SECONDS);
}
/** number of nanoseconds of this duration */
public long nanos() {
return nanos;
}
/**
* See {@link Time#parseElapsedTime(String)};
* also accepts "forever" (and for those who prefer things exceedingly accurate, "practically_forever").
* Also see {@link #of(Object)}. */
public static Duration parse(String textualDescription) {
if (Strings.isBlank(textualDescription)) return null;
if ("null".equalsIgnoreCase(textualDescription)) return null;
if ("forever".equalsIgnoreCase(textualDescription)) return Duration.PRACTICALLY_FOREVER;
if ("practicallyforever".equalsIgnoreCase(textualDescription)) return Duration.PRACTICALLY_FOREVER;
if ("practically_forever".equalsIgnoreCase(textualDescription)) return Duration.PRACTICALLY_FOREVER;
return new Duration((long) Time.parseElapsedTimeAsDouble(textualDescription), TimeUnit.MILLISECONDS);
}
/** creates new {@link Duration} instance of the given length of time */
public static Duration days(Number n) {
return new Duration((long) (n.doubleValue() * TimeUnit.DAYS.toNanos(1)), TimeUnit.NANOSECONDS);
}
/** creates new {@link Duration} instance of the given length of time */
public static Duration hours(Number n) {
return new Duration((long) (n.doubleValue() * TimeUnit.HOURS.toNanos(1)), TimeUnit.NANOSECONDS);
}
/** creates new {@link Duration} instance of the given length of time */
public static Duration minutes(Number n) {
return new Duration((long) (n.doubleValue() * TimeUnit.MINUTES.toNanos(1)), TimeUnit.NANOSECONDS);
}
/** creates new {@link Duration} instance of the given length of time */
public static Duration seconds(Number n) {
return new Duration((long) (n.doubleValue() * TimeUnit.SECONDS.toNanos(1)), TimeUnit.NANOSECONDS);
}
/** creates new {@link Duration} instance of the given length of time */
public static Duration millis(Number n) {
return new Duration((long) (n.doubleValue() * TimeUnit.MILLISECONDS.toNanos(1)), TimeUnit.NANOSECONDS);
}
/** creates new {@link Duration} instance of the given length of time */
public static Duration nanos(Number n) {
return new Duration(n.longValue(), TimeUnit.NANOSECONDS);
}
public static Function millisToStringRounded() { return millisToStringRounded; }
private static Function millisToStringRounded = new Function() {
@Override
@Nullable
public String apply(@Nullable Number input) {
if (input == null) return null;
return Duration.millis(input).toStringRounded();
}
};
public static Function secondsToStringRounded() { return secondsToStringRounded; }
private static Function secondsToStringRounded = new Function() {
@Override
@Nullable
public String apply(@Nullable Number input) {
if (input == null) return null;
return Duration.seconds(input).toStringRounded();
}
};
/** tries to convert given object to a Duration, parsing strings, treating numbers as millis, etc;
* throws IAE if not convertible */
public static Duration of(Object o) {
if (o == null) return null;
if (o instanceof Duration) return (Duration)o;
if (o instanceof String) return parse((String)o);
if (o instanceof Number) return millis((Number)o);
if (o instanceof Stopwatch) return millis(((Stopwatch)o).elapsed(TimeUnit.MILLISECONDS));
try {
// this allows it to work with groovy TimeDuration
Method millisMethod = o.getClass().getMethod("toMilliseconds");
return millis((Long)millisMethod.invoke(o));
} catch (Exception e) {
// probably no such method
}
throw new IllegalArgumentException("Cannot convert "+o+" (type "+o.getClass()+") to a duration");
}
public static Duration of(long value, TimeUnit unit) {
return new Duration(value, unit);
}
public static Duration max(Duration first, Duration second) {
return checkNotNull(first, "first").nanos >= checkNotNull(second, "second").nanos ? first : second;
}
public static Duration min(Duration first, Duration second) {
return checkNotNull(first, "first").nanos <= checkNotNull(second, "second").nanos ? first : second;
}
public static Duration untilUtc(long millisSinceEpoch) {
return millis(millisSinceEpoch - System.currentTimeMillis());
}
public static Duration sinceUtc(long millisSinceEpoch) {
return millis(System.currentTimeMillis() - millisSinceEpoch);
}
public Duration add(Duration other) {
return nanos(nanos() + other.nanos());
}
public Duration subtract(Duration other) {
return nanos(nanos() - other.nanos());
}
public Duration multiply(long x) {
return nanos(nanos() * x);
}
public Duration times(long x) {
return multiply(x);
}
/** as #multiply(long), but approximate due to the division (nano precision) */
public Duration multiply(double d) {
return nanos(nanos() * d);
}
public Duration half() {
return multiply(0.5);
}
/** see {@link Time#sleep(long)} */
public static void sleep(Duration duration) {
Time.sleep(duration);
}
/** returns a new started {@link CountdownTimer} with this duration */
public CountdownTimer countdownTimer() {
return CountdownTimer.newInstanceStarted(this);
}
public boolean isPositive() {
return nanos() > 0;
}
public boolean isNegative() {
return nanos() < 0;
}
public boolean isLongerThan(Duration x) {
return compareTo(x) > 0;
}
public boolean isLongerThan(Stopwatch stopwatch) {
return isLongerThan(Duration.millis(stopwatch.elapsed(TimeUnit.MILLISECONDS)));
}
public boolean isShorterThan(Duration x) {
return compareTo(x) < 0;
}
public boolean isShorterThan(Stopwatch stopwatch) {
return isShorterThan(Duration.millis(stopwatch.elapsed(TimeUnit.MILLISECONDS)));
}
/** returns the larger of this value or the argument */
public Duration lowerBound(Duration alternateMinimumValue) {
if (isShorterThan(alternateMinimumValue)) return alternateMinimumValue;
return this;
}
/** returns the smaller of this value or the argument */
public Duration upperBound(Duration alternateMaximumValue) {
if (isLongerThan(alternateMaximumValue)) return alternateMaximumValue;
return this;
}
/** @deprecated since 0.7.0 use {@link #lowerBound(Duration)} */ @Deprecated
public Duration minimum(Duration alternateMinimumValue) {
return lowerBound(alternateMinimumValue);
}
/** @deprecated since 0.7.0 use {@link #upperBound(Duration)} */ @Deprecated
/** returns the smaller of this value or the argument */
public Duration maximum(Duration alternateMaximumValue) {
return upperBound(alternateMaximumValue);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy