Какой самый простой способ десериализации времени, читаемого человеком, в Java?

Мне нужно иметь настраиваемое время ожидания для проекта, который читает различные конфигурации из файла YAML.

Я заметил, что java.time.Duration имеет метод parse, который используется Джексоном для десериализации строк продолжительности. Проблема в том, что он использует форматирование ISO-8601 и ожидает, что продолжительность PnDTnHnMn.nS формат. В то время как это хорошая идея следовать стандартам, просить людей предоставить время ожидания как PT10M это не лучший вариант и 10m является предпочтительным.

Я написал собственный десериализатор для полей длительности, но кажется странным, что Джексон не может справиться с этим по умолчанию.

Какой самый простой способ десериализации человека дружественным 10m, 5s а также 1h в java.time.Duration используя Jackson ObjectMapper?

1 ответ

Решение

"Самый простой" способ десериализации человека дружественным 10m, 5s а также 1h скорее всего, это сочетание регулярных выражений и кода Java.

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);
}

Тестовое задание

System.out.println(parseHuman("1h"));
System.out.println(parseHuman("1 hour 200 minutes"));
System.out.println(parseHuman("3600 secs"));
System.out.println(parseHuman("2h3m4s"));

Выход

PT1H
PT4H20M
PT1H
PT2H3M4S
Другие вопросы по тегам