/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package org.gnunet.util; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A specific point in time. * * @author Florian Dold */ public class AbsoluteTime implements Comparable { private static final Logger logger = LoggerFactory .getLogger(AbsoluteTime.class); /** * Constant for 'the beginning of time' in our frame. */ public final static AbsoluteTime ZERO = new AbsoluteTime(0); public final static AbsoluteTime FOREVER = new AbsoluteTime(Long.MAX_VALUE); /** * Gets the current time. * * @return the current time */ public static AbsoluteTime now() { return new AbsoluteTime(System.currentTimeMillis()); } private final long abs_value; public AbsoluteTime(final long abs_value) { this.abs_value = abs_value; } /** * Adds a relative time value to an absolute time. * * @param duration duration to add to {@literal this} * @return {@literal this + duration} */ public AbsoluteTime add(RelativeTime duration) { if (abs_value == Long.MAX_VALUE || duration.isForever()) { return AbsoluteTime.FOREVER; } if (abs_value + duration.getMilliseconds() < abs_value) { Thread.dumpStack(); return AbsoluteTime.FOREVER; } return new AbsoluteTime(abs_value + duration.getMilliseconds()); } /** * Calculates the estimate time of arrival/completion for an operation. * * @param start * when did the operation start? * @param finished * how much has been done? * @param total * how much must be done overall (same unit as for "finished") * @return remaining duration for the operation, assuming it continues at * the same speed */ public static RelativeTime calculateETA(final AbsoluteTime start, final long finished, final long total) { if (finished >= total) { return RelativeTime.ZERO; } if (finished == 0) { return RelativeTime.FOREVER; } final RelativeTime dur = start.getDuration(); final double exp = dur.getMilliseconds() * total / (double) finished; return new RelativeTime((long) exp); } /** * {@inheritDoc} */ @Override public boolean equals(Object other) { return other instanceof AbsoluteTime && compareTo((AbsoluteTime) other) == 0; } /** * {@inheritDoc} */ @Override public int hashCode() { return (int) this.abs_value; } /** * {@inheritDoc} */ @Override public int compareTo(AbsoluteTime other) { if (this.abs_value < other.abs_value) { return -1; } if (this.abs_value > other.abs_value) { return 1; } return 0; } /** * {@inheritDoc} */ @Override public String toString() { if (this.isForever()) { return "AbsoluteTime(FOREVER)"; } return "AbsoluteTime("+this.abs_value+")"; } /** * Check if a deadline is due. * @return true if NOW is greater than the given time, false otherwise */ public boolean isDue() { return this.abs_value < now().abs_value; } /** * Does this AbsoluteTime value represent forever? * * @return this==FOREVER */ public boolean isForever() { return this.abs_value == Long.MAX_VALUE; } /** * Calculates the difference between two absolute times. * * @param other ... * @return this - other */ public RelativeTime getDifference(final AbsoluteTime other) { if (other.abs_value == Long.MAX_VALUE) { return RelativeTime.FOREVER; } return new RelativeTime(abs_value - other.abs_value); } /** * Gets the duration of an operation as the difference of the current time * and {@literal this}. * * @return this - now */ public RelativeTime getDuration() { assert abs_value != Long.MAX_VALUE; return getDifference(AbsoluteTime.now()); } /** * Returns the milliseconds since some fixed point of reference. * * @return the absolute time in milliseconds */ public long getMilliseconds() { return abs_value; } /** * Calculates the remaining time relative to now. * * @return this - now */ public RelativeTime getRemaining() { if (abs_value == Long.MAX_VALUE) { return RelativeTime.FOREVER; } return getDifference(AbsoluteTime.now()); } /** * Returns the maximum of two time values. * * @param other ... * @return max(this,other) */ public AbsoluteTime max(final AbsoluteTime other) { return abs_value >= other.abs_value ? this : other; } /** * Returns the minimum of two time values. * * @param other ... * @return min(this,other) */ public AbsoluteTime min(final AbsoluteTime other) { return abs_value <= other.abs_value ? this : other; } /** * Subtracts a relative time value to an absolute time * * @param duration ... * @return this - duration */ public AbsoluteTime subtract(final RelativeTime duration) { if (abs_value <= duration.getMilliseconds()) { return AbsoluteTime.ZERO; } if (abs_value == Long.MAX_VALUE) { return this; } return new AbsoluteTime(abs_value - duration.getMilliseconds()); } /** * Get a serializable message corresponding to this AbsoluteTime. * * @return a serializable message corresponding to this AbsoluteTime */ public AbsoluteTimeMessage asMessage() { return new AbsoluteTimeMessage(this); } /** * Get the AbsoluteTime from a AbsoluteTimeMessage. * * @param m serializable representation of an AbsoluteTime * * @return the real AbsoluteTime associated with m */ public static AbsoluteTime fromNetwork(AbsoluteTimeMessage m) { return m.value__ < 0 ? AbsoluteTime.FOREVER : new AbsoluteTime(m.value__); } }