用于解析人类可读算术计算的数据库
Date library for parsing human readable arithmetic calculations
我正在编写一个 QA 测试自动化程序,人们将在其中输入人类可读的持续时间字符串,这些字符串具有 now - 5d
、yesterday
、now + 8 days
等值的算术运算,我需要将它们解析为 java 8 LocalDateTime
个实例。
简单地说,我需要这样的实用程序:
LocalDateTime nowMinus5Days = DurationUtil.parseHumanReadableDuration("now - 5d")
如何在 Java 中编写代码?或者是否有一些已经存在的库我应该使用而不是试图重新发明轮子?
我认为几乎不可能(或至少很难)涵盖每个可能的字符串输入到有效日期的转换。它甚至可能需要一些智能的自然语言处理。
我建议使用一组为输入公开的字段,并将它们 convert 到所需的对象。如果有最终用户,您可以让用户 select 无论他们想要添加还是减去日期,然后呈现一个文本输入,他们可以在其中输入天数。您可以将 "Yesterday" 和 "Tomorrow" 之类的输入作为特殊输入处理。
Java 的日期包非常有用,并且有 methods 用于添加和减去给定的天数。
这是一个起点。我猜你会想要进一步详细说明。
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单独出现时,它被视为月份)。期间或持续时间内不允许有 space。
可以想到的进一步发展包括:
- 添加更多字词:
today
、tomorrow
;考虑允许大写和混合大小写。
- 允许单位完整并带有 space,例如
8 days
。在最终解析为 Period
. 之前,进一步的正则表达式会将其转换为 8d
- 不允许模棱两可的
2m
强制用户指定例如 2m0d
(2 个月 0 天)或 2m0s
(2 分钟 0 秒)。或者强制大写 M
表示月份,小写 m
表示分钟。
- 复杂的部分:为无法解析的字符串提供有用的错误消息。
我正在编写一个 QA 测试自动化程序,人们将在其中输入人类可读的持续时间字符串,这些字符串具有 now - 5d
、yesterday
、now + 8 days
等值的算术运算,我需要将它们解析为 java 8 LocalDateTime
个实例。
简单地说,我需要这样的实用程序:
LocalDateTime nowMinus5Days = DurationUtil.parseHumanReadableDuration("now - 5d")
如何在 Java 中编写代码?或者是否有一些已经存在的库我应该使用而不是试图重新发明轮子?
我认为几乎不可能(或至少很难)涵盖每个可能的字符串输入到有效日期的转换。它甚至可能需要一些智能的自然语言处理。
我建议使用一组为输入公开的字段,并将它们 convert 到所需的对象。如果有最终用户,您可以让用户 select 无论他们想要添加还是减去日期,然后呈现一个文本输入,他们可以在其中输入天数。您可以将 "Yesterday" 和 "Tomorrow" 之类的输入作为特殊输入处理。
Java 的日期包非常有用,并且有 methods 用于添加和减去给定的天数。
这是一个起点。我猜你会想要进一步详细说明。
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单独出现时,它被视为月份)。期间或持续时间内不允许有 space。
可以想到的进一步发展包括:
- 添加更多字词:
today
、tomorrow
;考虑允许大写和混合大小写。 - 允许单位完整并带有 space,例如
8 days
。在最终解析为Period
. 之前,进一步的正则表达式会将其转换为 - 不允许模棱两可的
2m
强制用户指定例如2m0d
(2 个月 0 天)或2m0s
(2 分钟 0 秒)。或者强制大写M
表示月份,小写m
表示分钟。 - 复杂的部分:为无法解析的字符串提供有用的错误消息。
8d