/* * 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 java.io.Serializable; import java.util.Date; import java.util.Objects; import java.util.concurrent.TimeUnit; public class Timestamp implements Comparable<Timestamp>, Serializable { private static final long serialVersionUID = 8827895112055791967L; public final long m_time; public final TimeUnit m_unit; public Timestamp(long time, TimeUnit unit) { m_time = time; m_unit = unit; } private long convert(TimeUnit unit) { return unit.convert(m_time, m_unit); } public long asSeconds() { return convert(TimeUnit.SECONDS); } public long asMillis() { return convert(TimeUnit.MILLISECONDS); } public Date asDate() { return new Date(convert(TimeUnit.MILLISECONDS)); } public TimeUnit getUnit() { return m_unit; } public Timestamp plus(long value, TimeUnit units) { TimeUnit finest = finest(m_unit, units); return new Timestamp(convert(finest) + finest.convert(value, units), finest); } public Timestamp plus(Duration d) { TimeUnit finest = finest(m_unit, d.getUnit()); return new Timestamp(convert(finest) + d.convert(finest), finest); } public Timestamp minus(long value, TimeUnit units) { TimeUnit finest = finest(m_unit, units); return new Timestamp(convert(finest) - finest.convert(value, units), finest); } public Timestamp minus(Duration d) { TimeUnit finest = finest(m_unit, d.getUnit()); return new Timestamp(convert(finest) - d.convert(finest), finest); } public Duration minus(Timestamp t) { if (t.gt(this)) throw new IllegalArgumentException("you can only subtract an earlier date from a later one... negative durations don't make sense"); TimeUnit finest = finest(m_unit, t.getUnit()); return new Duration(convert(finest) - t.convert(finest), finest); } public boolean lt(Timestamp other) { return compareTo(other) < 0; } public boolean lte(Timestamp other) { return lt(other) || equals(other); } public boolean gt(Timestamp other) { return compareTo(other) > 0; } public boolean gte(Timestamp other) { return gt(other) || equals(other); } public Timestamp stepFloor(long stepSize, TimeUnit units) { return new Timestamp((convert(units) / stepSize) * stepSize, units); } public Timestamp stepFloor(Duration d) { return stepFloor(d.getDuration(), d.getUnit()); } public Timestamp stepCeiling(long stepSize, TimeUnit units) { long v = convert(units); return ((v % stepSize) == 0) ? new Timestamp(v, units) : new Timestamp(((v / stepSize) + 1) * stepSize, units); } public Timestamp stepCeiling(Duration d) { return stepCeiling(d.getDuration(), d.getUnit()); } @Override public boolean equals(Object other) { if (!(other instanceof Timestamp)) return false; return compareTo((Timestamp) other) == 0; } @Override public int hashCode() { return Objects.hashCode(Long.valueOf(convert(TimeUnit.NANOSECONDS))); } @Override public int compareTo(Timestamp o) { TimeUnit unit = finest(getUnit(), o.getUnit()); return convert(unit) < o.convert(unit) ? -1 : (convert(unit) > o.convert(unit) ? 1 : 0); } @Override public String toString() { return String.format("%s[%s]", getClass().getSimpleName(), asDate()); } public static Timestamp now() { return new Timestamp(System.currentTimeMillis(), TimeUnit.MILLISECONDS); } public static Timestamp fromEpochMillis(long millis) { return new Timestamp(millis, TimeUnit.MILLISECONDS); } public static Timestamp fromEpochSeconds(long seconds) { return new Timestamp(seconds, TimeUnit.SECONDS); } public static Timestamp fromDate(Date d) { return fromEpochMillis(d.getTime()); } static boolean isFiner(TimeUnit unit1, TimeUnit unit2) { long c = unit2.convert(1, unit1); return c == 0; } static TimeUnit finest(TimeUnit unit1, TimeUnit unit2) { return isFiner(unit1, unit2) ? unit1 : unit2; } }