package com.github.pfichtner.jrunalyser.base.data; import java.io.Serializable; import java.util.concurrent.TimeUnit; import com.google.common.base.Function; import com.google.common.collect.Interner; import com.google.common.collect.Interners; import com.google.common.collect.Ordering; import com.google.common.primitives.Doubles; public class DefaultDuration implements Duration, Serializable { private static final long serialVersionUID = -602982443795102202L; private final static long fix = TimeUnit.DAYS.toMillis(1); private static final Interner<DefaultDuration> interner = Interners .newWeakInterner(); private static Function<Duration, TimeUnit> getTimeUnit = new Function<Duration, TimeUnit>() { @Override public TimeUnit apply(Duration duration) { return duration.getTimeUnit(); } }; private static final Ordering<Duration> orderByTimeUnit = Ordering .natural().onResultOf(getTimeUnit); private final TimeUnit timeUnit; private final double value; private DefaultDuration(double value, TimeUnit timeUnit) { this.value = value; this.timeUnit = timeUnit; } public static DefaultDuration of(double value, TimeUnit timeUnit) { return interner.intern(new DefaultDuration(value, timeUnit)); } @Override public TimeUnit getTimeUnit() { return this.timeUnit; } @Override public double getValue(TimeUnit timeUnit) { return convertTo(timeUnit).value; } @Override public DefaultDuration convertTo(TimeUnit targetUnit) { double x = this.value * fix; return targetUnit == this.timeUnit ? this : DefaultDuration.of( (((double) targetUnit.convert((long) x, this.timeUnit)) / fix), targetUnit); } private TimeUnit findSmallerUnit(final Duration other) { return orderByTimeUnit.min(this, other).getTimeUnit(); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((this.timeUnit == null) ? 0 : this.timeUnit.hashCode()); long temp; temp = Double.doubleToLongBits(this.value); result = prime * result + (int) (temp ^ (temp >>> 32)); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; DefaultDuration other = (DefaultDuration) obj; if (this.timeUnit != other.timeUnit) return false; if (Double.doubleToLongBits(this.value) != Double .doubleToLongBits(other.value)) return false; return true; } @Override public int compareTo(Duration other) { final TimeUnit smaller = findSmallerUnit(other); return Doubles.compare(getValue(smaller), other.getValue(smaller)); } @Override public Duration add(Duration other) { return DefaultDuration.of(this.value + getOtherVal(other), this.timeUnit); } @Override public Duration subtract(Duration other) { return DefaultDuration.of(this.value - getOtherVal(other), this.timeUnit); } @Override public Duration divide(double divider) { return DefaultDuration.of(this.value / divider, this.timeUnit); } @Override public Duration multiply(double multiplier) { return DefaultDuration.of(this.value * multiplier, this.timeUnit); } private double getOtherVal(Duration other) { return other.convertTo(this.timeUnit).getValue(this.timeUnit); } @Override public String toString() { return "DefaultDuration[timeUnit=" + this.timeUnit + ", value=" + this.value + "]"; } }