DurationParser.java
package net.morimekta.terminal.args.parser;
import net.morimekta.terminal.args.ArgException;
import net.morimekta.terminal.args.ValueParser;
import java.time.Duration;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static java.lang.Integer.parseInt;
import static java.lang.Long.parseLong;
import static java.time.Duration.ofDays;
import static java.time.Duration.ofHours;
import static java.time.Duration.ofMillis;
import static java.time.Duration.ofMinutes;
import static java.time.Duration.ofNanos;
import static java.time.Duration.ofSeconds;
/**
* A duration parser.
*/
public class DurationParser implements ValueParser<Duration> {
@Override
public Duration parse(String value) {
try {
Matcher duration = DURATION_COMPLEX.matcher(value);
if (duration.matches()) {
var out = Duration.ZERO;
out = updatedDuration(out, duration.group("weeks"), s -> ofDays(7L * parseInt(s)));
out = updatedDuration(out, duration.group("days"), s -> ofDays(parseInt(s)));
out = updatedDuration(out, duration.group("hours"), s -> ofHours(parseInt(s)));
out = updatedDuration(out, duration.group("minutes"), s -> ofMinutes(parseInt(s)));
out = updatedDuration(out, duration.group("seconds"), s -> {
var parts = s.split("\\.");
if (parts.length == 2) {
var nanos = parts[1] + "0".repeat(9 - parts[1].length());
return ofSeconds(parseLong(parts[0]), parseInt(nanos));
}
return ofSeconds(parseLong(s));
});
out = updatedDuration(out, duration.group("millis"), s -> ofMillis(parseInt(s)));
out = updatedDuration(out, duration.group("nanos"), s -> ofNanos(parseInt(s)));
if (duration.group("minus") != null) {
return out.negated();
}
return out;
}
} catch (Exception e) {
throw new ArgException("Invalid duration: %s", e.getMessage(), e);
}
throw new ArgException("Expected duration string, but found: '%s'", value);
}
private static Duration updatedDuration(Duration orig, String amount, Function<String, Duration> parser) {
if (amount == null) {
return orig;
} else {
return orig.plus(parser.apply(amount));
}
}
private static final Pattern DURATION_COMPLEX = Pattern.compile(
"(?<minus>-)?" +
"(?:(?<weeks>\\d+) ?(?:w|weeks?) ?)?" +
"(?:(?<days>\\d+) ?(?:d|days?) ?)?" +
"(?:(?<hours>\\d+) ?(?:h|hours?) ?)?" +
"(?:(?<minutes>\\d+) ?(?:m|min|minutes?) ?)?" +
"(?:(?<seconds>\\d+(?:\\.\\d{1,9})?) ?(?:s|sec|seconds?) ?)?" +
"(?:(?<millis>\\d+) ?(?:ms|millis?) ?)?" +
"(?:(?<nanos>\\d+) ?(?:ns|nanos?))?");
}