Long
object.
*/
public class ValueDuration extends ValueSimpleValueDuration
object wrapping the specified value
.
*
* @param value the value to wrap
*/
public ValueDuration(Long value) {
super(value);
}
/* Kryo needs a no-args constructor */
private ValueDuration() {
}
@Override
public Type getType() {
return TypePrimitive.DURATION;
}
@Override
public Value getDefaultValue() {
return new ValueDuration(0l);
}
/**
* Constructs a new ValueDuration
object from the specified amounts of different time units.
*
* @param seconds a number of full seconds
* @param milliseconds a number of milliseconds (an absolute value does not have to be lower than 1000)
*/
public ValueDuration(long seconds, long milliseconds) {
this(seconds * 1000l + milliseconds);
}
/**
* Constructs a new ValueDuration
object from the specified amounts of different time units.
*
* @param minutes a number of full minutes
* @param seconds a number of full seconds (an absolute value does not have to be lower than 60)
* @param milliseconds a number of milliseconds (an absolute value does not have to be lower than 1000)
*/
public ValueDuration(long minutes, long seconds, long milliseconds) {
this(minutes * 60l + seconds, milliseconds);
}
/**
* Constructs a new ValueDuration
object from the specified amounts of different time units.
*
* @param hours a number of full hours
* @param minutes a number of full minutes (an absolute value does not have to be lower than 60)
* @param seconds a number of full seconds (an absolute value does not have to be lower than 60)
* @param milliseconds a number of milliseconds (an absolute value does not have to be lower than 1000)
*/
public ValueDuration(long hours, long minutes, long seconds, long milliseconds) {
this(hours * 60l + minutes, seconds, milliseconds);
}
/**
* Constructs a new ValueDuration
object from the specified amounts of different time units.
*
* @param days a number of full days
* @param hours a number of full hours (an absolute value does not have to be lower than 24)
* @param minutes a number of full minutes (an absolute value does not have to be lower than 60)
* @param seconds a number of full seconds (an absolute value does not have to be lower than 60)
* @param milliseconds a number of milliseconds (an absolute value does not have to be lower than 1000)
*/
public ValueDuration(long days, long hours, long minutes, long seconds, long milliseconds) {
this(days * 24l + hours, minutes, seconds, milliseconds);
}
/**
* Constructs a new ValueDuration
object from its textual representation. The representation has
* format: sd hh:mm:ss.lll
where:
* s
is a sign (+
or -
),d
is a number of days,hh
is a number of hours (between 00
and 23
),mm
is a number of minutes (between 00
and 59
),ss
is a number of seconds (between 00
and 59
),lll
is a number of milliseconds (between 000
and 999
).
* All fields are obligatory.
*
* @param value a textual representation of a duration
* @throws IllegalArgumentException if value
does not meet described rules
*/
public ValueDuration(String value) {
this(parseDuration(value));
}
private static long parseDuration(String value) {
Matcher matcher = DURATION_PATTERN.matcher(value);
if (!matcher.matches()) {
throw new InvalidFormatException();
}
long result = parseLongGroup(matcher, "days");
result *= 24;
result += parseLongGroup(matcher, "hours");
result *= 60;
result += parseLongGroup(matcher, "minutes");
result *= 60;
result += parseLongGroup(matcher, "seconds");
result *= 1000;
result += parseLongGroup(matcher, "milliseconds");
result *= matcher.group("sign").equals("+") ? 1 : -1;
return result;
}
/**
* @param matcher A regex matcher
* @param group The name of a group matched by matcher
that
* should have captured a number.
* @return The parsed number.
*/
private static long parseLongGroup(Matcher matcher, String group) {
return Long.parseLong(matcher.group(group));
}
@Override
public ValueBoolean isLowerThan(Value value) {
sameTypesOrThrow(value, Operation.COMPARE);
if(isNull() || value.isNull())
return new ValueBoolean(null);
return new ValueBoolean(getValue() < ((ValueDuration)value).getValue());
}
@Override
public ValueDuration addValue(Value value) {
sameTypesOrThrow(value, Operation.ADD);
if (isNull() || value.isNull()) {
return new ValueDuration((Long) null);
}
return new ValueDuration(getValue() + ((ValueDuration)value).getValue());
}
@Override
public ValueDuration subtract(Value value) {
sameTypesOrThrow(value, Operation.SUBTRACT);
if (isNull() || value.isNull())
return new ValueDuration((Long) null);
return new ValueDuration(getValue() - ((ValueDuration)value).getValue());
}
@Override
public ValueDuration multiply(Value value) {
if (!value.getType().isCompatible(TypePrimitive.INTEGER)) {
throw new IncompatibleTypesException(getType(), value.getType(), Operation.MULTIPLY);
}
if (isNull() || value.isNull()) {
return new ValueDuration((Long) null);
}
return new ValueDuration(getValue() * ((ValueInt)value).getValue());
}
@Override
public Value divide(Value value) {
if (!value.getType().isCompatible(TypePrimitive.INTEGER)) {
throw new IncompatibleTypesException(getType(), value.getType(), Operation.MULTIPLY);
}
if (isNull() || value.isNull()) {
return new ValueDuration((Long) null);
}
if (((ValueInt)value).getValue() == 0l) {
throw new ArithmeticException("Division by zero.");
}
return new ValueDuration(getValue() / ((ValueInt)value).getValue());
}
@Override
public ValueDuration modulo(Value value) {
if (!value.getType().isCompatible(TypePrimitive.INTEGER)) {
throw new IncompatibleTypesException(getType(), value.getType(), Operation.MULTIPLY);
}
if (isNull() || value.isNull()) {
return new ValueDuration((Long) null);
}
if (((ValueInt)value).getValue() == 0l) {
throw new ArithmeticException("Division by zero.");
}
return new ValueDuration(getValue() % ((ValueInt)value).getValue());
}
@Override
public ValueDuration negate() {
if(isNull()) {
return new ValueDuration((Long) null);
}
return new ValueDuration(-getValue());
}
private String makeString() {
long remainingUnits = getValue();
boolean positive = remainingUnits >= 0;
remainingUnits = positive ? remainingUnits : -remainingUnits;
long milliseconds = remainingUnits % 1000;
remainingUnits /= 1000;
long seconds = remainingUnits % 60;
remainingUnits /= 60;
long minutes = remainingUnits % 60;
remainingUnits /= 60;
long hours = remainingUnits % 24;
remainingUnits /= 24;
long days = remainingUnits;
return (positive ? "+" : "-") + String.format("%d %02d:%02d:%02d.%03d",
days, hours, minutes, seconds, milliseconds
);
}
@Override
public Value convertTo(Type type) {
switch(type.getPrimaryType()) {
case STRING:
return getValue() == null? ValueString.NULL_STRING : new ValueString(makeString());
case INT:
return new ValueInt(getValue() == null? null : getValue());
case DURATION:
return this;
default:
throw new UnsupportedConversionException(getType(), type);
}
}
}