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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With