我正在编写一个质量检查测试自动化程序,人们将使用算术运算输入具有诸如now - 5d
,yesterday
,now + 8 days
之类值的人类可读持续时间字符串,我需要将其解析为Java 8 LocalDateTime
实例。
简单地说,我需要像这样的实用程序:
LocalDateTime nowMinus5Days = DurationUtil.parseHumanReadableDuration("now - 5d")
java.time
实用程序或其他实用程序是否已执行此操作,因此我不必从头开始实现某些功能?
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
强制设置为分钟。