在使用Aviator写脚本的时候,要计算两个时间字符串,得到处理时长。处理时间的时候,如果时间字符串是不固定。想传时间字符串进去,然后进行替换计算该如何处理呢?
处理思路:
用“.getTime()”进行标记这个是时间字符串,要把字符串时间替换为日期时间。
如果结束时间,则处理时长字段为空""
// 把时间字符串转换为时间
public static Date strToDateTime(String time) {
Date dateTime = null;
try {
dateTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(time);
} catch (ParseException e) {
e.printStackTrace();
}
return dateTime;
}
// 正则表达式 用于获取 $xxx.yyyy.getTime() 中 yyyy的内容,
public static List<String> getMatchGetTime(String expression, String mark) {
String pattern = "\\$" + mark + "\\.([\\[\\]0-9a-zA-Z_.]*)" + "\\.getTime\\(\\)";
Pattern p = Pattern.compile(pattern);
Matcher m = p.matcher(expression);
List<String> column = new ArrayList<>();
while (m.find()) {
column.add(m.group(1));
}
return column;
}
// 特殊处理时间 使用.getTime() 作为要把该字符串之间转为Date时间进行处理
// 用$row 表示当前数据, $param 表示参数
public static void testDateGetTimeCalculateUnitByGetTime(Map<String, Object> data, Map<String, Object> param) {
String expression = "let st = $row.startTimeStr.getTime(); let startTime = getTime(st); " +
"let ed = $row.endTimeStr.getTime(); let endTime = getTime(ed); " +
"return '处理人:'+$row.staffName+',处理时长为:'+(endTime - startTime)/$param.divisor+$param.unit;";
// 获取到带getTime()字段的内容
List<String> matchGetTime = getMatchGetTime(expression, "row");
// 对时间和表达式进行替换
boolean calcuate = true; // 判断是否要计算,如果有时间为空,就不进行计算,直接赋值为空
Map<String, Object> env = new HashMap<>();
// 复制一份数据,用于后面put要计算的date值
Map<String, Object> rowParam = new HashMap<>(data);
env.put("$row", rowParam);
env.put("$param", param);
Object result;
if (CollectionUtils.isNotEmpty(matchGetTime)) {
for (String e : ListUtils.emptyIfNull(matchGetTime)) {
String dateResult = rowParam.get(e).toString();
if (StringUtils.isBlank(dateResult)) {// 如果没有对应的值就不进行计算了
calcuate = false;
break;
} else {
result = strToDateTime(dateResult);
}
// 添加新的名字,用于计算
String reName = e + "Calculate";
// 替换表达式的内容,去掉.getTime(), 不然无法识别
expression = expression.replace(e + ".getTime()", reName);
rowParam.put(reName, result);
}
}
if (calcuate) {
// 启用基于反射的方法查找和调用
AviatorEvaluator.setFunctionMissing(JavaMethodReflectionFunctionMissing.getInstance());
Expression compiledExp = AviatorEvaluator.compile(expression);
try {
result = compiledExp.execute(env);
} catch (Exception e) {
e.printStackTrace();
result = "";
}
} else {
result = "";
}
data.put("calculte", result);
}
public static void main(String args[]) {
Map<String, Object> data = new HashMap<>();
String startTime = "2022-03-25 10:25:25";
String endTime = "2022-03-25 11:25:25";
data.put("startTimeStr", startTime);
data.put("endTimeStr", endTime);
data.put("staffName", "小李");
Map<String, Object> param = new HashMap<>();
param.put("divisor", 1000);
param.put("unit", "s");
System.out.println("结束时间正常:");
testDateGetTimeCalculateUnitByGetTime(data,param);
System.out.println(JSON.toJSON(data));
System.out.println("结束时间异常:");
data.put("endTimeStr", "");
testDateGetTimeCalculateUnitByGetTime(data,param);
System.out.println(JSON.toJSON(data));
}
结束时间正常:
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/beanutils/BeanIntrospector
at com.googlecode.aviator.ClassExpression.executeDirectly(ClassExpression.java:73)
at com.googlecode.aviator.BaseExpression.execute(BaseExpression.java:136)
at com.ffcs.iod.ms.workflow.report.config.AviatorTest.getDateGetTimeCalculateUnitByGetTime(AviatorTest.java:251)
at com.ffcs.iod.ms.workflow.report.config.AviatorTest.testDateGetTimeCalculateUnitByGetTime(AviatorTest.java:277)
at com.ffcs.iod.ms.workflow.report.config.AviatorTest.main(AviatorTest.java:442)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.beanutils.BeanIntrospector
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 5 more
原因: 漏了对应commons-beanutils的jar包
处理:引入commons-beanutils的包
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.4</version>
</dependency>
在用Aviator处理时间的时候,把字符串时间转换时间,再替换表达式里面对应的值,再进行计算和处理。 如果没有指定具体时间字段,需要特殊处理,比如上面的使用“.getTime()”进行识别和表达式替换。 对于一些脚本处理不来的内容,使用java进行处理,再进行替换。