I need to have configurable timeout for a project, which reads different configs from YAML file.
I noticed that java.time.Duration
has method parse which is used by Jackson to deserialize duration strings. The problem is that it uses ISO-8601 formatting and expects the duration to have PnDTnHnMn.nS
format. While it is a good idea to follow standards, asking people provide timeout as PT10M
is not the best option and 10m
is preferred.
I did write a custom deserializer for duration fields, but seems strange that Jackson can't handle this by default.
What is the easiest way to deserialize human friendly 10m
, 5s
and 1h
to java.time.Duration
using Jackson ObjectMapper?
"Easiest" way to deserialize human friendly 10m
, 5s
and 1h
is likely a combination of regex and Java code.
public static Duration parseHuman(String text) {
Matcher m = Pattern.compile("\\s*(?:(\\d+)\\s*(?:hours?|hrs?|h))?" +
"\\s*(?:(\\d+)\\s*(?:minutes?|mins?|m))?" +
"\\s*(?:(\\d+)\\s*(?:seconds?|secs?|s))?" +
"\\s*", Pattern.CASE_INSENSITIVE)
.matcher(text);
if (! m.matches())
throw new IllegalArgumentException("Not valid duration: " + text);
int hours = (m.start(1) == -1 ? 0 : Integer.parseInt(m.group(1)));
int mins = (m.start(2) == -1 ? 0 : Integer.parseInt(m.group(2)));
int secs = (m.start(3) == -1 ? 0 : Integer.parseInt(m.group(3)));
return Duration.ofSeconds((hours * 60L + mins) * 60L + secs);
}
Test
System.out.println(parseHuman("1h"));
System.out.println(parseHuman("1 hour 200 minutes"));
System.out.println(parseHuman("3600 secs"));
System.out.println(parseHuman("2h3m4s"));
Output
PT1H
PT4H20M
PT1H
PT2H3M4S