/* * Copyright 2014, The OpenNMS Group * * Licensed 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.opennms.newts.api; import static com.google.common.base.Preconditions.checkNotNull; import java.io.Serializable; import java.util.Objects; import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Duration implements Comparable<Duration>, Serializable { private static final long serialVersionUID = -6758879321662337772L; private static final Pattern s_pattern = Pattern.compile("([\\d]+)(ms|[wdhms])"); private final long m_duration; private final TimeUnit m_unit; public Duration(long duration, TimeUnit unit) { m_duration = duration; m_unit = unit; } public long convert(TimeUnit unit) { return unit.convert(getDuration(), getUnit()); } public long asMillis() { return convert(TimeUnit.MILLISECONDS); } public long asSeconds() { return convert(TimeUnit.SECONDS); } public static Duration days(long days) { return new Duration(days, TimeUnit.DAYS); } public static Duration hours(long hours) { return new Duration(hours, TimeUnit.HOURS); } public static Duration minutes(long minutes) { return new Duration(minutes, TimeUnit.MINUTES); } public static Duration seconds(long seconds) { return new Duration(seconds, TimeUnit.SECONDS); } public static Duration millis(long millis) { return new Duration(millis, TimeUnit.MILLISECONDS); } public static Duration parse(String durationSpec) { checkNotNull(durationSpec, "durationSpec argument"); // If we replace every matched term with an empty string, the result should be // an empty string, otherwise there are invalid characters in the given duration if (!"".equals(s_pattern.matcher(durationSpec).replaceAll(""))) { throw new IllegalArgumentException(String.format("%s is not a valid duration", durationSpec)); } Matcher matcher = s_pattern.matcher(durationSpec); Duration tally = null; while (matcher.find()) { Integer value = Integer.parseInt(matcher.group(1)); String unit = matcher.group(2); Duration r; switch (unit) { case "w": r = Duration.days((long)value * 7); break; case "d": r = Duration.days(value); break; case "h": r = Duration.hours(value); break; case "m": r = Duration.minutes(value); break; case "s": r = Duration.seconds(value); break; case "ms": r = Duration.millis(value); break; default: throw new RuntimeException(String.format("%s is an unknown unit; this is a bug!", unit)); } tally = tally != null ? tally.plus(r) : r; } if (tally == null) { // We didn't find any terms throw new IllegalArgumentException(String.format("%s is not a valid duration", durationSpec)); } return tally; } public long getDuration() { return m_duration; } public TimeUnit getUnit() { return m_unit; } public Duration plus(Duration o) { TimeUnit u = Timestamp.finest(getUnit(), o.getUnit()); return new Duration(convert(u) + o.convert(u), u); } public Duration times(long value) { return new Duration(getDuration() * value, getUnit()); } public long divideBy(Duration o) { TimeUnit u = Timestamp.finest(getUnit(), o.getUnit()); return convert(u) / o.convert(u); } public boolean isMultiple(Duration o) { TimeUnit u = Timestamp.finest(getUnit(), o.getUnit()); return this.gte(o) && ((convert(u) % o.convert(u)) == 0); } @Override public String toString() { return String.format("%s[%d, %s]", getClass().getSimpleName(), m_duration, getUnit()); } @Override public int compareTo(Duration o) { TimeUnit unit = Timestamp.finest(getUnit(), o.getUnit()); return convert(unit) < o.convert(unit) ? -1 : (convert(unit) > o.convert(unit) ? 1 : 0); } @Override public boolean equals(Object o) { if (!(o instanceof Duration)) return false; return compareTo((Duration) o) == 0; } @Override public int hashCode() { return Objects.hashCode(Long.valueOf(convert(TimeUnit.NANOSECONDS))); } public boolean lt(Duration o) { return compareTo(o) == -1; } public boolean gt(Duration o) { return compareTo(o) == 1; } public boolean lte(Duration o) { return compareTo(o) <= 0; } public boolean gte(Duration o) { return compareTo(o) >= 0; } }