package de.invesdwin.util.time;
import javax.annotation.concurrent.Immutable;
import de.invesdwin.util.time.duration.Duration;
import de.invesdwin.util.time.fdate.FTimeUnit;
/**
* This class represents an instant relative to the application start in nanoseconds.
*
* @author subes
*
*/
@Immutable
public class Instant extends Number implements Comparable<Object> {
public static final FTimeUnit DEFAULT_TIMEUNIT = FTimeUnit.NANOSECONDS;
public static final Instant DUMMY = new Instant(0, DEFAULT_TIMEUNIT);
private static final long serialVersionUID = 1L;
private final long startNanos;
public Instant() {
this.startNanos = System.nanoTime();
}
public Instant(final long start, final FTimeUnit timeUnit) {
this.startNanos = DEFAULT_TIMEUNIT.convert(start, timeUnit);
}
@Override
public String toString() {
return toString(DEFAULT_TIMEUNIT);
}
public String toString(final FTimeUnit timeUnit) {
return new Duration(this, new Instant(), timeUnit).toString();
}
public Duration toDuration() {
return new Duration(this, new Instant());
}
/**
* Sleeps relative to this instant. Thus may not sleep at all if the time has already passed.
*/
public void sleepRelative(final long amount, final FTimeUnit timeUnit) throws InterruptedException {
final long alreadyPassedNanos = new Duration(this, new Instant()).longValue();
final long durationNanos = DEFAULT_TIMEUNIT.convert(amount, timeUnit);
DEFAULT_TIMEUNIT.sleep(durationNanos - alreadyPassedNanos);
}
public void sleepRelativeTo(final Duration duration) throws InterruptedException {
sleepRelative(duration.longValue(), duration.getTimeUnit());
}
@Override
public int intValue() {
return intValue(DEFAULT_TIMEUNIT);
}
public int intValue(final FTimeUnit timeUnit) {
return Long.valueOf(timeUnit.convert(startNanos, DEFAULT_TIMEUNIT)).intValue();
}
@Override
public long longValue() {
return longValue(DEFAULT_TIMEUNIT);
}
public long longValue(final FTimeUnit timeUnit) {
return Long.valueOf(timeUnit.convert(startNanos, DEFAULT_TIMEUNIT)).longValue();
}
@Override
public float floatValue() {
return floatValue(DEFAULT_TIMEUNIT);
}
public float floatValue(final FTimeUnit timeUnit) {
return Long.valueOf(timeUnit.convert(startNanos, DEFAULT_TIMEUNIT)).floatValue();
}
@Override
public double doubleValue() {
return doubleValue(DEFAULT_TIMEUNIT);
}
public double doubleValue(final FTimeUnit timeUnit) {
return Long.valueOf(timeUnit.convert(startNanos, DEFAULT_TIMEUNIT)).doubleValue();
}
public boolean before(final Instant time) {
return longValue(FTimeUnit.NANOSECONDS) < time.longValue(FTimeUnit.NANOSECONDS);
}
public boolean after(final Instant zeitpunkt) {
return longValue(FTimeUnit.NANOSECONDS) > zeitpunkt.longValue(FTimeUnit.NANOSECONDS);
}
@Override
public boolean equals(final Object obj) {
if (obj == null || !(obj instanceof Instant)) {
return false;
} else {
final Instant o1 = this;
final Instant o2 = (Instant) obj;
return ((Long) o1.startNanos).equals(o2.startNanos);
}
}
@Override
public int hashCode() {
return ((Long) startNanos).hashCode();
}
@Override
public int compareTo(final Object o) {
if (o == null || !(o instanceof Instant)) {
return 1;
} else {
final Instant o1 = this;
final Instant o2 = (Instant) o;
return ((Long) o1.startNanos).compareTo(o2.startNanos);
}
}
public static Instant min(final Instant first, final Instant second) {
if (first == null) {
return second;
} else if (second == null) {
return first;
} else if (first.before(second)) {
return first;
} else {
return second;
}
}
}