计算处理时长 日期计算 SpringEL
要根据日期时间,计算处理时长。比如
{
"创建时间": "2021-04-21",
"结束时间": "2021-04-29",
"开始处理时间": "2021-04-22 09:00:28",
"处理完成时间": "2021-04-28 09:02:28" ,
"总数": 17
}
要计算 “处理完成时间 - 开始处理时间” 的结果
公式: "(#处理完成时间-#开始处理时间)/1000"
要计算 “结束时间 - 创建时间” 的结果
公式:"(#结束时间-#创建时间)/(1000*60*60*24)"
处理思路:
1,如果字段是固定的,把相应的内容转换为时间戳,再进行计算
2,如果字段不是固定的,根据配置的来,这时候考虑使用SpringEl。
使用SpringEl的话:
1,时间字符串转换为时间戳进行计算
2,对应字段是中文的,要替换为英文才能计算。先提取要计算的字段,重新赋值,也替换公式的内容。最后进行计算。
直接上代码:
代码:
处理代码:
public static void main(String[] args) {
String beginTime = "2021-04-22 09:00:28";
String endTime = "2021-04-22 09:10:33";
String beginDate = "2021-04-22";
String endDate = "2021-04-25";
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("开始处理时间", beginTime);
dataMap.put("处理完成时间", endTime);
dataMap.put("创建时间", beginDate);
dataMap.put("结束时间", endDate);
String formula1 = "(#处理完成时间-#开始处理时间)/1000";
String formula2 = "(#结束时间-#创建时间)/(1000*60*60*24)";
compulate(dataMap, formula1);
System.out.println("==========");
compulate(dataMap, formula2);
}
public static void compulate(Map<String, Object> dataMap, String formula){
// 1,获取公式字段里面的字段
List<String> calculateField = RegUtils.getFormulaParam(formula);
// 引入新的参数
String calculte = "calculte";
AtomicInteger atomicInteger = new AtomicInteger(0);
Map<String, String> matchFormulaMap = new HashMap<>();
// 重置formula 和 数据类型
String newParam;
for (String s : ListUtils.emptyIfNull(calculateField)) {
newParam = calculte + atomicInteger;
matchFormulaMap.put(s, newParam); // 添加新的参数,用于数值处理的时候匹配
formula = formula.replaceAll(s, newParam);
atomicInteger.getAndIncrement();
}
// 日期转换
changeFiledDataType(calculateField, matchFormulaMap, dataMap);
System.out.println(dataMap);
String result = SpelExpressionUtils.parseExpression(dataMap, formula, "0");
System.out.println(result);
}
private static void changeFiledDataType(List<String> calculateField, Map<String, String> matchFormulaMap,
Map<String, Object> dataMap) {
String value, matchKey;
for (String s : ListUtils.emptyIfNull(calculateField)) {
value = MapUtils.getString(dataMap, s);
matchKey = matchFormulaMap.get(s);
if (StringUtils.isNotBlank(value) && DateTimeUtils.isValidDateStr(value)) {// 日期类型转换为long类型
dataMap.put(matchKey, DateTimeUtils.toLongDateStr(value));
} else {
dataMap.put(matchKey, dataMap.get(s));
}
}
}
工具类:
正则的参考 匹配中文
日期的参考 字符串转时间戳
SpringEl的:
public class SpelExpressionUtils {
private static final ExpressionParser PARSER = new SpelExpressionParser();
public static ExpressionParser getParser() {
return PARSER;
}
private SpelExpressionUtils() {
}
public static String parseExpression(Map<String, Object> data, String formula) {
return parseExpression(data, formula, "0.00");
}
public static Double parseDoubleExpression(Map<String, Object> data, Expression expression) {
EvaluationContext ctx = new StandardEvaluationContext();
if (Objects.nonNull(data)) {
data.forEach(ctx::setVariable);
}
return expression.getValue(ctx, Double.class);
}
public static Double parseDoubleExpression(Map<String, Object> data, String formula) {
Expression expression = PARSER.parseExpression(formula);
return parseDoubleExpression(data, expression);
}
public static String parseExpression(Map<String, Object> data, String formula, String pattern) {
try {
Double expressionResult = parseDoubleExpression(data, formula);
if (Objects.nonNull(expressionResult)) {
return decimalFormat(expressionResult, pattern);
}
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
private static String decimalFormat(Double value, String pattern) {
if (StringUtils.isBlank(pattern)) {
pattern = "0";
}
DecimalFormat df = new DecimalFormat(pattern);
df.setRoundingMode(RoundingMode.HALF_UP);
return df.format(value);
}
结果:
{开始处理时间=2021-04-22 09:00:28, 创建时间=2021-04-22, calculte1=1619053228000, 处理完成时间=2021-04-22 09:10:33, 结束时间=2021-04-25, calculte0=1619053833000}
605
==========
{开始处理时间=2021-04-22 09:00:28, 创建时间=2021-04-22, calculte1=1619020800000, 处理完成时间=2021-04-22 09:10:33, 结束时间=2021-04-25, calculte0=1619280000000}
3
如果要加单位,就再拼接
总结:
计算处理时长,动态处理的话,还是使用SpringEl比较好处理。可以根据公式自行变化。一般公式是配置在数据库,读取配置再进行处理。
复杂的例子代码参考:计算处理时长