
org.echocat.jomon.runtime.util.Duration Maven / Gradle / Ivy
/*****************************************************************************************
* *** BEGIN LICENSE BLOCK *****
*
* Version: MPL 2.0
*
* echocat Jomon, Copyright (c) 2012-2014 echocat
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* *** END LICENSE BLOCK *****
****************************************************************************************/
package org.echocat.jomon.runtime.util;
import org.echocat.jomon.runtime.util.Duration.Adapter;
import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import javax.annotation.concurrent.ThreadSafe;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.io.Serializable;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import static java.lang.Character.isDigit;
import static java.lang.Character.isWhitespace;
import static java.lang.Long.valueOf;
import static java.lang.Math.round;
import static java.lang.Thread.currentThread;
import static java.util.Collections.unmodifiableMap;
import static java.util.concurrent.TimeUnit.*;
import static org.echocat.jomon.runtime.StringUtils.addElement;
/**
* Synopsis
* A {@link Duration} represents a duration of time. The minimum unit are milliseconds.
*
* It could be defined by an amount of milliseconds, a combination of amount and {@link TimeUnit} and a string pattern.
*
* Pattern
*
* Syntax
* <amount>[<unit>][[ ]...]
*
* Units
*
* S
/ms
: milliseconds
* s
: seconds
* m
: minutes
* h
: hours
* d
: days
* w
: weeks
*
*
* Examples
*
* new Duration("1ms").toMilliSeconds() == 1
* new Duration("1s").toMilliSeconds() == 1,000
* new Duration("1m").toMilliSeconds() == 60,000
* new Duration("1m10s").toMilliSeconds() == 70,000
* new Duration("1m 10s").toMilliSeconds() == 70,000
* new Duration("15").toMilliSeconds() == 15
* new Duration("2s 15").toMilliSeconds() == 2,015
*
*
*/
@Immutable
@ThreadSafe
@XmlJavaTypeAdapter(Adapter.class)
public class Duration implements Comparable, Serializable {
private static final long serialVersionUID = 3L;
private static final int MAXIMUM_NANOSECONDS_VALUE = 999999;
public static void sleep(@Nonnull Duration duration) throws InterruptedException {
duration.sleep();
}
public static void sleep(@Nonnull String duration) throws InterruptedException {
sleep(new Duration(duration));
}
public static void sleep(@Nonnegative long amount, @Nonnull TimeUnit unit) throws InterruptedException {
sleep(new Duration(amount, unit));
}
public static void sleep(@Nonnegative long milliSeconds) throws InterruptedException {
sleep(new Duration(milliSeconds));
}
public static void sleep(@Nonnegative long milliSeconds, @Nonnegative int nanoSeconds) throws InterruptedException {
sleep(new Duration(milliSeconds, nanoSeconds));
}
public static void sleepSafe(@Nonnull Duration duration) throws GotInterruptedException {
duration.sleepSafe();
}
public static void sleepSafe(@Nonnull String duration) throws GotInterruptedException {
sleepSafe(new Duration(duration));
}
public static void sleepSafe(@Nonnegative long amount, @Nonnull TimeUnit unit) throws GotInterruptedException {
sleepSafe(new Duration(amount, unit));
}
public static void sleepSafe(@Nonnegative long milliSeconds) throws GotInterruptedException {
sleepSafe(new Duration(milliSeconds));
}
public static void sleepSafe(@Nonnegative long milliSeconds, @Nonnegative int nanoSeconds) throws GotInterruptedException {
sleepSafe(new Duration(milliSeconds, nanoSeconds));
}
@Nonnull
public static Duration duration(@Nonnull Duration duration) {
return duration;
}
@Nullable
public static Duration duration(@Nullable String duration) {
return duration != null ? new Duration(duration) : null;
}
@Nullable
public static Duration duration(@Nonnegative long milliSeconds) {
return duration(milliSeconds, 0);
}
@Nullable
public static Duration duration(@Nonnegative long milliSeconds, @Nonnegative int nanoSeconds) {
return new Duration(milliSeconds, nanoSeconds);
}
@Nonnull
public static Duration durationOf(@Nonnull Duration duration) {
return duration(duration);
}
@Nullable
public static Duration durationOf(@Nullable String duration) {
return duration(duration);
}
@Nullable
public static Duration durationOf(@Nonnegative long duration) {
return duration(duration);
}
@Nullable
public static Duration durationOf(@Nonnegative long milliSeconds, @Nonnegative int nanoSeconds) {
return duration(milliSeconds, nanoSeconds);
}
@Nonnegative
private final long _milliSeconds;
@Nonnegative
private final int _nanoSeconds;
public Duration(@Nonnegative long milliSeconds) {
this(milliSeconds, 0);
}
/**
* @param plain See {@link Duration}
*/
public Duration(@Nonnull String plain) throws IllegalArgumentException {
this(parsePattern(plain));
}
public Duration(@Nonnegative long duration, @Nonnull TimeUnit unit) {
this(new MilliAndNanoSeconds(duration, unit));
}
public Duration(@Nonnegative long milliSeconds, @Nonnegative int nanoSeconds) {
this(new MilliAndNanoSeconds(milliSeconds, nanoSeconds));
}
public Duration(@Nonnull Date from, @Nonnull Date to) {
if (from.after(to)) {
throw new IllegalArgumentException("From " + from + " is after to " + to + "?");
}
_milliSeconds = to.getTime() - from.getTime();
_nanoSeconds = 0;
}
protected Duration(@Nonnull MilliAndNanoSeconds seconds) {
_milliSeconds = seconds.getMilliSeconds();
_nanoSeconds = seconds.getNanoSeconds();
if (_milliSeconds < 0) {
throw new IllegalArgumentException("MilliSeconds value is negative.");
}
if (_nanoSeconds < 0) {
throw new IllegalArgumentException("NanoSeconds value is negative.");
}
if (_nanoSeconds > MAXIMUM_NANOSECONDS_VALUE) {
throw new IllegalArgumentException("NanoSecond value out of range: is " + _nanoSeconds + "; maximum " + MAXIMUM_NANOSECONDS_VALUE);
}
}
@Nonnull
public Duration plus(@Nullable Duration duration) {
final long calculatedNanos = getNanoSeconds() + duration.getNanoSeconds();
final long additionalMillis = calculatedNanos / 1000000L;
final int nanos = (int) (calculatedNanos - (additionalMillis * 1000000L));
return new Duration(getMilliSeconds() + duration.getMilliSeconds() + additionalMillis, nanos);
}
@Nonnull
public Duration plus(@Nullable String duration) {
return plus(duration != null ? new Duration(duration) : null);
}
@Nonnull
public Duration plus(@Nonnegative long amount, @Nonnull TimeUnit unit) {
return plus(new Duration(amount, unit));
}
@Nonnull
public Duration plus(@Nonnegative long milliSeconds) {
return plus(new Duration(milliSeconds));
}
@Nonnull
public Duration minus(@Nullable Duration duration) {
final long calculatedMillis = getMilliSeconds() - duration.getMilliSeconds();
final int calculatedNanos = getNanoSeconds() - duration.getNanoSeconds();
final int nanos = calculatedNanos >= 0 ? calculatedNanos : 1000000 + calculatedNanos;
final long millis = calculatedMillis - (calculatedNanos >= 0 ? 0 : 1);
if (millis < 0) {
throw new IllegalArgumentException("The result of " + this + " minus " + duration + " is negative.");
}
return new Duration(millis, nanos);
}
@Nonnull
public Duration minus(@Nullable String duration) {
return minus(duration != null ? new Duration(duration) : null);
}
@Nonnull
public Duration minus(@Nonnegative long amount, @Nonnull TimeUnit unit) {
return minus(new Duration(amount, unit));
}
@Nonnull
public Duration minus(@Nonnegative long milliSeconds) {
return minus(new Duration(milliSeconds));
}
@Nonnull
public Duration multiplyBy(@Nonnegative double what) {
if (what < 0) {
throw new IllegalArgumentException();
}
final double calculatedMillis = getMilliSeconds() * what;
final long millis = (long) calculatedMillis;
final long additionalNanos = round((calculatedMillis - (double) millis) * 1000000d);
final long calculatedNanos = round(getNanoSeconds() * what) + additionalNanos;
final long additionalMillis = calculatedNanos / 1000000L;
final int nanos = (int) (calculatedNanos - (additionalMillis * 1000000L));
return new Duration(millis + additionalMillis, nanos);
}
@Nonnull
public Duration dividedBy(@Nonnegative double what) {
if (what < 0) {
throw new IllegalArgumentException();
}
final double calculatedMillis = getMilliSeconds() / what;
final long millis = round(calculatedMillis);
final long additionalNanos = round((calculatedMillis - (double) millis) * 1000000d);
final long calculatedNanos = round(getNanoSeconds() / what) + additionalNanos;
final long additionalMillis = calculatedNanos / 1000000L;
final int nanos = (int) (calculatedNanos - (additionalMillis * 1000000L));
return new Duration(millis + additionalMillis, nanos);
}
@Nonnull
public Duration multiplyBy(@Nonnegative long what) {
if (what < 0) {
throw new IllegalArgumentException();
}
final long millis = getMilliSeconds() * what;
final long calculatedNanos = getNanoSeconds() * what;
final long additionalMillis = calculatedNanos / 1000000L;
final int nanos = (int) (calculatedNanos - (additionalMillis * 1000000L));
return new Duration(millis + additionalMillis, nanos);
}
@Nonnull
public Duration dividedBy(@Nonnegative long what) {
if (what < 0) {
throw new IllegalArgumentException();
}
final long millis = getMilliSeconds() / what;
final long calculatedNanos = getNanoSeconds() / what;
final long additionalMillis = calculatedNanos / 1000000L;
final int nanos = (int) (calculatedNanos - (additionalMillis * 1000000L));
return new Duration(millis + additionalMillis, nanos);
}
@Nonnull
public Duration trim(@Nonnull TimeUnit toUnit) {
final Duration result;
if (toUnit == NANOSECONDS) {
result = this;
} else if (toUnit == MICROSECONDS) {
result = new Duration(getMilliSeconds(), (getNanoSeconds() / 1000) * 1000);
} else {
result = new Duration(toUnit.toMillis(toUnit.convert(getMilliSeconds(), MILLISECONDS)));
}
return result;
}
/**
* @return the duration in milli seconds.
* @deprecated Please use {@link #in(TimeUnit)} in the future.
*/
@Nonnegative
@Deprecated
public long toMilliSeconds() {
return in(MILLISECONDS);
}
@Nonnegative
protected long getMilliSeconds() {
return _milliSeconds;
}
@Nonnegative
protected int getNanoSeconds() {
return _nanoSeconds;
}
@Nonnegative
public long in(@Nonnull TimeUnit unit) {
final long milliSeconds = getMilliSeconds();
final int nanoSeconds = getNanoSeconds();
final long result;
if (unit != MICROSECONDS && unit != NANOSECONDS && milliSeconds > 0 && nanoSeconds > 0) {
result = unit.convert((milliSeconds * 1000L) + (long) nanoSeconds, NANOSECONDS);
} else if (milliSeconds > 0) {
result = unit.convert(milliSeconds, MILLISECONDS);
} else {
result = unit.convert(nanoSeconds, NANOSECONDS);
}
return result;
}
/**
* @return See {@link Duration pattern}.
*/
@Nonnull
public String toPattern() {
return toPattern(getMilliSeconds(), getNanoSeconds());
}
@Nonnull
public String toPattern(@Nonnull TimeUnit minimalUnit) {
return trim(minimalUnit).toPattern();
}
@Nonnull
public Map toUnitToValue() {
return toUnitToValue(getMilliSeconds(), getNanoSeconds());
}
public boolean isEmpty() {
return getMilliSeconds() <= 0 && getNanoSeconds() <= 0;
}
public boolean hasContent() {
return getMilliSeconds() > 0 || getNanoSeconds() > 0;
}
public boolean isLessThan(@Nullable String other) {
return isLessThan(other != null ? new Duration(other) : null);
}
public boolean isLessThan(@Nullable Duration other) {
return other != null ? isLessThan(other.getMilliSeconds(), other.getNanoSeconds()) : isLessThan(0);
}
public boolean isLessThan(@Nonnegative long amount, @Nonnull TimeUnit unit) {
return isLessThan(new Duration(amount, unit));
}
public boolean isLessThan(@Nonnegative long milliSeconds) {
return isLessThan(milliSeconds, 0);
}
protected boolean isLessThan(@Nonnegative long milliSeconds, @Nonnegative int nanoSeconds) {
final long localMilliSeconds = getMilliSeconds();
return localMilliSeconds < milliSeconds || (localMilliSeconds == milliSeconds && getNanoSeconds() < nanoSeconds);
}
public boolean isLessThanOrEqualTo(@Nullable String other) {
return isLessThanOrEqualTo(other != null ? new Duration(other) : null);
}
public boolean isLessThanOrEqualTo(@Nullable Duration other) {
return other != null ? isLessThanOrEqualTo(other.getMilliSeconds(), other.getNanoSeconds()) : isLessThanOrEqualTo(0);
}
public boolean isLessThanOrEqualTo(@Nonnegative long amount, @Nonnull TimeUnit unit) {
return isLessThanOrEqualTo(new Duration(amount, unit));
}
public boolean isLessThanOrEqualTo(@Nonnegative long milliSeconds) {
return isLessThanOrEqualTo(milliSeconds, 0);
}
protected boolean isLessThanOrEqualTo(@Nonnegative long milliSeconds, @Nonnegative int nanoSeconds) {
final long localMilliSeconds = getMilliSeconds();
return localMilliSeconds < milliSeconds || (localMilliSeconds == milliSeconds && getNanoSeconds() <= nanoSeconds);
}
public boolean isGreaterThan(@Nullable String other) {
return isGreaterThan(other != null ? new Duration(other) : null);
}
public boolean isGreaterThan(@Nullable Duration other) {
return other != null ? isGreaterThan(other.getMilliSeconds(), other.getNanoSeconds()) : isGreaterThan(0);
}
public boolean isGreaterThan(@Nonnegative long amount, @Nonnull TimeUnit unit) {
return isGreaterThan(new Duration(amount, unit));
}
public boolean isGreaterThan(@Nonnegative long milliSeconds) {
return isGreaterThan(milliSeconds, 0);
}
protected boolean isGreaterThan(@Nonnegative long milliSeconds, @Nonnegative int nanoSeconds) {
final long localMilliSeconds = getMilliSeconds();
return localMilliSeconds > milliSeconds || (localMilliSeconds == milliSeconds && getNanoSeconds() > nanoSeconds);
}
public boolean isGreaterThanOrEqualTo(@Nullable String other) {
return isGreaterThanOrEqualTo(other != null ? new Duration(other) : null);
}
public boolean isGreaterThanOrEqualTo(@Nullable Duration other) {
return other != null ? isGreaterThanOrEqualTo(other.getMilliSeconds(), other.getNanoSeconds()) : isGreaterThanOrEqualTo(0);
}
public boolean isGreaterThanOrEqualTo(@Nonnegative long amount, @Nonnull TimeUnit unit) {
return isGreaterThanOrEqualTo(new Duration(amount, unit));
}
public boolean isGreaterThanOrEqualTo(@Nonnegative long milliSeconds) {
return isGreaterThanOrEqualTo(milliSeconds, 0);
}
protected boolean isGreaterThanOrEqualTo(@Nonnegative long milliSeconds, @Nonnegative int nanoSeconds) {
final long localMilliSeconds = getMilliSeconds();
return localMilliSeconds > milliSeconds || (localMilliSeconds == milliSeconds && getNanoSeconds() >= nanoSeconds);
}
public void sleep() throws InterruptedException {
Thread.sleep(getMilliSeconds(), getNanoSeconds());
}
public void sleepSafe() throws GotInterruptedException {
try {
sleep();
} catch (final InterruptedException e) {
currentThread().interrupt();
throw new GotInterruptedException(e);
}
}
@Override
public int compareTo(Duration other) {
final int resultOnMilliSeconds = compare(getMilliSeconds(), other != null ? other.getMilliSeconds() : 0);
final int result;
if (resultOnMilliSeconds == 0) {
result = compare(getNanoSeconds(), other != null ? other.getNanoSeconds() : 0);
} else {
result = resultOnMilliSeconds;
}
return result;
}
private static int compare(@Nonnegative long self, @Nonnegative long other) {
// noinspection NestedConditionalExpression
final int result = ((self < other) ? -1 : ((self == other) ? 0 : 1));
return result;
}
@Override
public int hashCode() {
final long milliSeconds = getMilliSeconds();
final int nanoSeconds = getNanoSeconds();
return (int) (milliSeconds ^ (milliSeconds >>> 32)) * nanoSeconds;
}
@Override
public boolean equals(Object o) {
final boolean result;
if (this == o) {
result = true;
} else if (o instanceof Duration) {
final Duration other = (Duration) o;
result = (getMilliSeconds() == other.getMilliSeconds())
&& (getNanoSeconds() == other.getNanoSeconds());
} else {
result = false;
}
return result;
}
@Override
public String toString() {
return toPattern();
}
@Nonnegative
protected static long oneUncheckedIntervalToMilliSeconds(@Nonnull String interval) {
final String trimmedInterval = interval.trim();
return trimmedInterval.isEmpty() ? 0 : oneIntervalToMilliSeconds(interval);
}
@Nonnegative
protected static long oneUncheckedIntervalToNanoSeconds(@Nonnull String interval) {
final String trimmedInterval = interval.trim();
return trimmedInterval.isEmpty() ? 0 : oneIntervalToNanoSeconds(interval);
}
@Nonnegative
protected static long oneIntervalToMilliSeconds(@Nonnull String interval) {
long value;
try {
value = valueOf(interval);
} catch (final NumberFormatException ignored) {
if (interval.length() >= 2) {
final long plainValue;
try {
plainValue = valueOf(interval.substring(0, interval.length() - 1));
} catch (final NumberFormatException e) {
throw new IllegalArgumentException("Don't know how to convert: " + interval, e);
}
final String mode = interval.substring(interval.length() - 1);
if (mode.equals("S")) {
value = plainValue;
} else if (mode.equals("s")) {
value = SECONDS.toMillis(plainValue);
} else if (mode.equals("m")) {
value = MINUTES.toMillis(plainValue);
} else if (mode.equals("h")) {
value = HOURS.toMillis(plainValue);
} else if (mode.equals("d")) {
value = DAYS.toMillis(plainValue);
} else if (mode.equals("w")) {
value = DAYS.toMillis(plainValue) * 7;
} else {
throw new IllegalArgumentException("Don't know how to convert: " + interval);
}
} else {
throw new IllegalArgumentException("Don't know how to convert: " + interval);
}
}
return value;
}
@Nonnegative
protected static long oneIntervalToNanoSeconds(@Nonnull String interval) {
long value;
try {
value = valueOf(interval);
} catch (final NumberFormatException ignored) {
if (interval.length() >= 2) {
final long plainValue;
try {
plainValue = valueOf(interval.substring(0, interval.length() - 1));
} catch (final NumberFormatException e) {
throw new IllegalArgumentException("Don't know how to convert: " + interval, e);
}
final String mode = interval.substring(interval.length() - 1);
if (mode.equals("n")) {
value = plainValue;
} else if (mode.equals("µ")) {
value = MICROSECONDS.toNanos(plainValue);
} else {
throw new IllegalArgumentException("Don't know how to convert: " + interval);
}
} else {
throw new IllegalArgumentException("Don't know how to convert: " + interval);
}
}
return value;
}
@Nonnegative
protected static MilliAndNanoSeconds parsePattern(@Nonnull String pattern) throws IllegalArgumentException {
StringBuilder sb = new StringBuilder();
final char[] chars = pattern.replace("ms", "S").replace("µs", "µ").replace("ns", "n").toCharArray();
long milli = 0;
long nano = 0;
for (final char c : chars) {
if (isWhitespace(c)) {
milli += oneUncheckedIntervalToMilliSeconds(sb.toString());
sb = new StringBuilder();
} else if (isDigit(c)) {
sb.append(c);
} else if (c == 'w' || c == 'd' || c == 'h' || c == 'm' || c == 's' || c == 'S') {
sb.append(c);
milli += oneUncheckedIntervalToMilliSeconds(sb.toString());
sb = new StringBuilder();
} else if (c == '\u00B5' || c == 'n') {
sb.append(c);
nano += oneUncheckedIntervalToNanoSeconds(sb.toString());
sb = new StringBuilder();
} else {
throw new IllegalArgumentException("Don't know how to convert: " + pattern);
}
}
milli += oneUncheckedIntervalToMilliSeconds(sb.toString());
final long toMuchMillis = nano / 1000000L;
milli += toMuchMillis;
nano -= toMuchMillis * 1000000L;
return new MilliAndNanoSeconds(milli, (int) nano);
}
protected static class MilliAndNanoSeconds {
@Nonnegative
private final long _milliSeconds;
@Nonnegative
private final int _nanoSeconds;
public MilliAndNanoSeconds(@Nonnegative long milliSeconds, @Nonnegative int nanoSeconds) {
_milliSeconds = milliSeconds;
_nanoSeconds = nanoSeconds;
}
public MilliAndNanoSeconds(@Nonnegative long duration, @Nonnull TimeUnit unit) {
if (unit == NANOSECONDS || unit == MICROSECONDS) {
final long fullNanoSeconds = unit.toNanos(duration);
_milliSeconds = fullNanoSeconds / 1000000L;
_nanoSeconds = (int) (fullNanoSeconds - (_milliSeconds * 1000000L));
} else {
_milliSeconds = unit.toMillis(duration);
_nanoSeconds = 0;
}
}
@Nonnegative
public long getMilliSeconds() {
return _milliSeconds;
}
@Nonnegative
public int getNanoSeconds() {
return _nanoSeconds;
}
}
@Nonnull
protected static String toPattern(@Nonnegative long milliseconds, @Nonnegative int nanoSeconds) {
final StringBuilder sb = new StringBuilder();
if (milliseconds > 0) {
appendPatternOf(milliseconds, sb);
}
if (nanoSeconds > 0) {
appendPatternOf(nanoSeconds, sb);
}
if (sb.length() == 0) {
sb.append("0ms");
}
return sb.toString();
}
protected static void appendPatternOf(@Nonnegative long milliseconds, @Nonnull StringBuilder to) {
final long days = milliseconds / 1000 / 60 / 60 / 24;
final long hours = (milliseconds / 1000 / 60 / 60) - (days * 24);
final long minutes = (milliseconds / 1000 / 60) - (days * 24 * 60) - (hours * 60);
final long seconds = (milliseconds / 1000) - (minutes * 60) - (hours * 60 * 60) - (days * 24 * 60 * 60);
final long ms = milliseconds - (seconds * 1000) - (minutes * 60 * 1000) - (hours * 1000 * 60 * 60) - (days * 24 * 60 * 60 * 1000);
if (days > 0) {
addElement(to, " ", days + "d");
}
if (hours > 0) {
addElement(to, " ", hours + "h");
}
if (minutes > 0) {
addElement(to, " ", minutes + "m");
}
if (seconds > 0) {
addElement(to, " ", seconds + "s");
}
if (ms > 0) {
addElement(to, " ", ms + "ms");
}
}
protected static void appendPatternOf(@Nonnegative int nanoSeconds, @Nonnull StringBuilder to) {
final int µs = nanoSeconds / 1000;
final int ns = nanoSeconds - (µs * 1000);
if (µs > 0) {
addElement(to, " ", µs + "µs");
}
if (ns > 0) {
addElement(to, " ", ns + "ns");
}
}
@Nonnull
protected static Map toUnitToValue(@Nonnegative long milliSeconds, @Nonnegative int nanoSeconds) {
final Map result = new LinkedHashMap<>();
appendUnitToValueOf(milliSeconds, result);
appendUnitToValueOf(nanoSeconds, result);
return unmodifiableMap(result);
}
protected static void appendUnitToValueOf(@Nonnegative long milliSeconds, @Nonnull Map to) {
final long days = milliSeconds / 1000 / 60 / 60 / 24;
final long hours = (milliSeconds / 1000 / 60 / 60) - (days * 24);
final long minutes = (milliSeconds / 1000 / 60) - (days * 24 * 60) - (hours * 60);
final long seconds = (milliSeconds / 1000) - (minutes * 60) - (hours * 60 * 60) - (days * 24 * 60 * 60);
final long ms = milliSeconds - (seconds * 1000) - (minutes * 60 * 1000) - (hours * 1000 * 60 * 60) - (days * 24 * 60 * 60 * 1000);
if (days > 0) {
to.put(DAYS, days);
}
if (hours > 0) {
to.put(HOURS, hours);
}
if (minutes > 0) {
to.put(MINUTES, minutes);
}
if (seconds > 0) {
to.put(SECONDS, seconds);
}
if (ms > 0) {
to.put(MILLISECONDS, ms);
}
}
protected static void appendUnitToValueOf(@Nonnegative int nanoSeconds, @Nonnull Map to) {
final long µs = nanoSeconds / 1000;
final long ns = nanoSeconds - (µs * 1000);
if (µs > 0) {
to.put(MICROSECONDS, µs);
}
if (ns > 0) {
to.put(NANOSECONDS, ns);
}
}
public static class Adapter extends XmlAdapter {
@Override
public Duration unmarshal(String v) throws Exception {
return v != null ? new Duration(v) : null;
}
@Override
public String marshal(Duration v) throws Exception {
return v != null ? v.toPattern() : null;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy