这篇博客将介绍Java 如何根据Cron表达式获取近几次任务执行时间。实际上使用 quartz 包 CronSequenceGenerator 以及TriggerUtils.computeFireTimes 俩种方法进行时间获取;
1. 效果图
2. 源码
<dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz</artifactId><version>2.3.0</version>
</dependency>
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.quartz.CronExpression;
import org.quartz.TriggerUtils;
import org.quartz.impl.triggers.CronTriggerImpl;
import org.springframework.scheduling.support.CronSequenceGenerator;import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Consumer;/****************************** Class Name: CronUtil* Description: <获取Cron表达式最近几次执行的时间>* @Author: Seminar* @create: 2022/11/02* @since: 1.0.0***************************/
@Slf4j
public class CronUtil {public void getTime() {String cronExpress = "0 */30 * * * ?";//此处为cron表达式cronExpress = "0 0/30 * * * ?";try {CronExpression cronExpression = new CronExpression(cronExpress);//导包import org.quartz.CronExpression;Date date = cronExpression.getTimeAfter(new Date());//将date转换为指定日期格式字符串SimpleDateFormat dataFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");String dateString = dataFormat.format(date);//dateString为转换后的日期格式log.info("{} {}", cronExpress, dateString);} catch (Exception e) {log.error("cron获取下次执行时间异常" + e);}}/*** 列出近cronCount次的执行时间** @param cronExpression cron表达式* @param cronCount cron时间次数* @param maxCronCount 最大cron时间次数* @return*/public static List<String> listCronRunTime(String cronExpression, Integer cronCount, Integer maxCronCount) {if (StringUtils.isBlank(cronExpression)) {throw new RuntimeException("Cron 表达式不能为空!");}if (!CronSequenceGenerator.isValidExpression(cronExpression)) {throw new RuntimeException("Cron格式不正确,Cron: " + cronExpression);}if (cronCount < 1) {cronCount = 1;}if (maxCronCount < 1) {maxCronCount = 100;}if (cronCount > maxCronCount) {cronCount = maxCronCount;}CronSequenceGenerator cronSequenceGenerator = new CronSequenceGenerator(cronExpression);List<String> cronTimeList = new ArrayList<>();Date nextTimePoint = new Date();SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");for (int i = 0; i < cronCount; i++) {nextTimePoint = cronSequenceGenerator.next(nextTimePoint);cronTimeList.add(sdf.format(nextTimePoint));}return cronTimeList;}/*** 列出近numTimes次的执行时间** @param cronExpression cron表达式* @param numTimes 下几次运行时间* @return*/public static List<String> getNextExecTime(String cronExpression, Integer numTimes) {List<String> list = new ArrayList<>();CronTriggerImpl cronTriggerImpl = new CronTriggerImpl();try {cronTriggerImpl.setCronExpression(cronExpression);} catch (ParseException e) {e.printStackTrace();}// 这个是重点,一行代码搞定List<Date> dates = TriggerUtils.computeFireTimes(cronTriggerImpl, null, numTimes);SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");for (Date date : dates) {list.add(dateFormat.format(date));}return list;}/*** Java8 通过foreach 遍历List,同时输出下标* 利用BiConsumer实现foreach循环支持index** @param biConsumer* @param <T>* @return*/public static <T> Consumer<T> forEachWithIndex(BiConsumer<T, Integer> biConsumer) {/*这里说明一下,我们每次传入forEach都是一个重新实例化的Consumer对象,在lambada表达式中我们无法对int进行++操作,我们模拟AtomicInteger对象,写个getAndIncrement方法,不能直接使用AtomicInteger哦*/class IncrementInt {int i = 0;public int getAndIncrement() {return i++;}}IncrementInt incrementInt = new IncrementInt();return t -> biConsumer.accept(t, incrementInt.getAndIncrement());}public static void main(String[] args) {CronUtil cronUtil = new CronUtil();cronUtil.getTime();String cron = "0 0/30 * * * ?"; // 0 0/30 * * * ? 每隔30分钟执行一次 同 0 */30 * * * ?cron = "0 0/5 14 * * ?"; // 0 0/5 14 * * ? 在每天下午2点到下午2:55期间的每5分钟触发log.info("cron: {}", cron);List<String> timeList = listCronRunTime(cron, 10, 100);timeList.stream().forEach(forEachWithIndex((item, index) -> {log.info("{} {}", index + 1, item);}));List<String> time2List = getNextExecTime(cron, 10);time2List.stream().forEach(x -> {log.info("---- {}", x);});}
}
参考
- 根据Cron表达式获取近几次任务执行时间(Spring + Quartz)
- cron表达式详解,cron表达式写法,cron表达式例子
- 根据cron表达式获取下次执行时间