Библиотека дат для анализа вычислений, читаемых человеком арифмети c - PullRequest
1 голос
/ 31 марта 2020

Я пишу программу автоматизации тестирования QA, где люди собираются вводить читаемые человеком строки длительности с арифметическими c операциями со значениями, такими как now - 5d, yesterday, now + 8 days, и мне нужно проанализировать их в java 8 LocalDateTime экземпляров.

Проще говоря, мне нужна такая утилита:

LocalDateTime nowMinus5Days = DurationUtil.parseHumanReadableDuration("now - 5d")

Как я могу кодировать это в Java? Или есть какая-то библиотека, которая уже существует, которую я должен использовать вместо попытки изобретать велосипед?

Ответы [ 2 ]

3 голосов
/ 04 апреля 2020

Вот отправная точка. Я предполагаю, что вы захотите уточнить это дальше.

private static Pattern relativeTimePattern
        = Pattern.compile("(\\w+)\\s*(?:([+-])\\s*(\\w+))?");
private static Map<String, Supplier<LocalDateTime>> bases
        = Map.of("now", () -> LocalDateTime.now(),
                "yesterday", () -> LocalDate.now().minusDays(1).atStartOfDay()); 

public static LocalDateTime parseRelativeTime(String timeString) {
    Matcher m = relativeTimePattern.matcher(timeString);
    if (m.matches()) {
        String baseString = m.group(1);
        LocalDateTime result = bases.get(baseString).get();
        String signString = m.group(2);
        if (signString != null) {
            boolean subtract = signString.equals("-");
            String diffString = m.group(3);
            TemporalAmount diff;
            try {
                diff = Period.parse("P" + diffString);
            } catch (DateTimeParseException dtpe) {
                // try a Duration instead
                diff = Duration.parse("PT" + diffString);
            }
            if (subtract) {
                result = result.minus(diff);
            } else {
                result = result.plus(diff);
            }
        }
        return result;
    } else {
        throw new IllegalArgumentException();
    }
}

Давайте попробуем это:

    System.out.println(parseRelativeTime("now - 5d"));
    System.out.println(parseRelativeTime("yesterday"));
    System.out.println(parseRelativeTime("now + 8d"));

Вывод, когда я только что запустил:

2020-03-30T09:49:18.300731
2020-04-03T00:00
2020-04-12T09:49:18.307784

Поскольку мой метод стоит, он принимает либо now и yesterday в нижнем регистре, за которыми необязательно следует знак (+ или -) и либо точка лет-месяцев-недель-дней или продолжительность часов-минут-секунд. Каждый из последних должен использовать одну буквенную аббревиатуру для единиц времени (y, m, w, d, h, m, s; когда двусмысленная m приходит одна, она принимается за месяцы). Внутри периода или продолжительности запрещены пробелы.

Возможные дальнейшие разработки включают:

  • Добавить больше слов: today, tomorrow; рассмотрите возможность использования заглавных и смешанных букв.
  • Разрешить единицы измерения полностью и с пробелом, например 8 days. Дальнейшее регулярное выражение преобразует это в 8d перед последним анализом в Period.
  • Запретить неоднозначное 2m, заставляя пользователя указать, например, 2m0d (2 месяца 0 дней) или 2m0s (2 минуты 0 секунд). Или задайте прописные буквы M для месяцев и строчные буквы m для минут.
  • Сложная часть: предоставьте полезные сообщения об ошибках для строк, которые не могут быть проанализированы.
1 голос
/ 31 марта 2020

Я думаю, что практически невозможно (или, по крайней мере, трудно) охватить преобразование каждого возможного ввода строки в допустимую дату. Это может даже потребовать некоторой интеллектуальной обработки естественного языка.

Я бы предложил использовать набор полей, доступных для ввода, и преобразовать их в нужный объект. Если есть конечный пользователь, пользователь может выбрать, хотят ли они добавить или вычесть дату, а затем представить текстовый ввод, в котором он может ввести количество дней. Вы можете обрабатывать входные данные, такие как «Вчера» и «Завтра», как специальные входные данные. Пакет дат

Java довольно полезен и содержит методов для сложения и вычитания заданного количества дней.

...