package edu.uw.zookeeper.common; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.google.common.base.Objects; import com.google.common.collect.ImmutableBiMap; import edu.uw.zookeeper.data.Serializes; public final class TimeValue implements Comparable<TimeValue> { public static TimeValue milliseconds(long value) { return new TimeValue(value, TimeUnit.MILLISECONDS); } public static TimeValue seconds(long value) { return new TimeValue(value, TimeUnit.SECONDS); } public static TimeValue create(long value, String unitText) { checkNotNull(unitText); TimeUnit unit = null; try { unit = TimeUnit.valueOf(unitText.toUpperCase()); } catch (IllegalArgumentException e) { unit = unitFromShortName(unitText); } if (unit == null) { throw new IllegalArgumentException(String.valueOf(unitText)); } return new TimeValue(value, unit); } public static TimeValue create(long value, TimeUnit unit) { return new TimeValue(value, unit); } @Serializes(from=String.class, to=TimeValue.class) public static TimeValue fromString(String text) { Matcher m = PATTERN.matcher(text); if (! m.matches()) { throw new IllegalArgumentException(text); } long value = Long.parseLong(m.group(1)); String unit = m.group(2); return create(value, unit); } public static String unitToShortName(TimeUnit unit) { String name = SHORT_UNIT_NAMES.get(unit); checkArgument(name != null, String.valueOf(unit)); return name; } public static TimeUnit unitFromShortName(String name) { TimeUnit unit = SHORT_UNIT_NAMES.inverse().get(name.toLowerCase()); checkArgument(unit != null, String.valueOf(name)); return unit; } protected static final ImmutableBiMap<TimeUnit, String> SHORT_UNIT_NAMES = ImmutableBiMap.<TimeUnit, String>builder() .put(TimeUnit.DAYS, "d") .put(TimeUnit.HOURS, "h") .put(TimeUnit.MINUTES, "m") .put(TimeUnit.SECONDS, "s") .put(TimeUnit.MILLISECONDS, "ms") .put(TimeUnit.MICROSECONDS, "us") .put(TimeUnit.NANOSECONDS, "ns") .build(); protected static String FORMAT = "%d %s"; protected static Pattern PATTERN = Pattern.compile("(\\d+)[ \t]*([a-zA-Z]+)"); private final long value; private final TimeUnit unit; public TimeValue(long value, TimeUnit unit) { this.value = value; this.unit = checkNotNull(unit); } public long value() { return value; } public TimeUnit unit() { return unit; } public long value(TimeUnit to) { return to.convert(value, unit); } public TimeValue convert(TimeUnit to) { return new TimeValue(value(to), to); } public TimeValue difference(TimeValue other) { Long diff = value - other.value(unit); return new TimeValue(diff, unit); } @Override public int compareTo(TimeValue other) { long diff = value - other.value(unit); return (int) diff; } @Override public String toString() { return String.format(FORMAT, value, SHORT_UNIT_NAMES.get(unit)); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (! (obj instanceof TimeValue)) { return false; } TimeValue other = (TimeValue) obj; return Objects.equal(value, other.value) && Objects.equal(unit, other.unit); } @Override public int hashCode() { return Objects.hashCode(value); } }