java定时任务 设置开始时间、结束时间;每周一、四、六执行;并且隔n周执行。最后计算所有执行时间

java定时任务 设置开始时间、结束时间;每周一、四、六执行;并且隔n周执行。最后计算所有执行时间)

定时任务需求

在一个特殊的项目需求中,我们设计一个定时任务,并算出它所有的执行时间点。

1.有开始时间和结束时间。

2.每周一、四、六执行(动态参数) 执行的时和分HH:mm(动态参数)

3.隔n周执行(动态参数)

4.算每次执行时间。

程序设计

参数 类型 说明
定时任务开始时间 startTime yyyy-MM-dd
定时任务结束时间 endTime yyyy-MM-dd
执行时间 executeTime HH:mm
周几执行列表 weekList: [0,1,2,3,4,5,6] 代表:[周日,周一,周二,周三,周四,周五,周六] cron中 [1,2,3,4,5,6,7] 代表:[周日,周一,周二,周三,周四,周五,周六]
隔几周执行一次 interval 数字n

依赖引入

xml 复制代码
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.3.2</version>
        </dependency>

程序

一、计算开始时间那周的周一时间

考虑隔周执行,一定要以开始时间那个周的周一为起点,否则时间会算错。

java 复制代码
 /**
     * 开始时间点的周一时间
     * @param startDate
     * @return
     */
    public static Date getMonday(Date startDate){
        /**
         * 计算给出时间的周一时间
         */
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(startDate);
        // 将小时、分钟、秒和毫秒字段设置为0
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        // 将日期设置为本周第一天(默认为周日)的前一天(即周一)
        calendar.add(Calendar.DAY_OF_WEEK, Calendar.MONDAY - calendar.get(Calendar.DAY_OF_WEEK));

        // 输出周一0点的时间
        return calendar.getTime();
    }

二、根据executeTime和weekList.get(n),计算每个cron表达式。

java 复制代码
/**
     *计算cron表达式
     *@param executeTime  执行时间 HH:mm
     * @param week   周几
     * @return cron表达式
     * @throws ParseException
     */
    public static String createCronStr(String executeTime, Integer week)  {
        String weekStr = String.valueOf(week + 1);
        // 设置cron表达式,周三,下午3点30分执行
        String cronExpression = "0 %1$s %2$s ? * %3$s";
        String[] times = executeTime.split(":");
        String hour = times[0];
        String minute = times[1];
        return String.format(cronExpression, minute, hour, weekStr);
    }

三、根据一和二得出的cron表达式和开始时间的那周的周一时间,计算每次定时任务执行的第一次时间。

java 复制代码
    /**
     * 计算下次执行时间
     * @param cronExpression cron
     * @param startTime2  开始时间(开始时间的周一时间)
     * @return
     * @throws ParseException
     */
    public static  Date getNextExecutionTime(String cronExpression, Date startTime2) throws ParseException {
        CronExpression cron = new CronExpression(cronExpression);
        Date nextExecutionTime = cron.getNextValidTimeAfter(startTime2);

        System.out.println("下次执行时间: " + nextExecutionTime);
        return nextExecutionTime;
    }

四、计算所有执行时间

java 复制代码
 /**
     *
     * @param startTime  定时任务开始时间  yyyy-MM-dd
     * @param endTime    定时任务结束时间  yyyy-MM-dd
     * @param executeTime  执行时间 HH:mm
     * @param weekList   周几执行列表  [0,1,2,3,4,5,6] 代表:[周日,周一,周二,周三,周四,周五,周六]
     * @param interval   隔几周执行一次
     * @return
     */
    public static List<String> getExecuteTimeList(String startTime, String endTime, String executeTime, List<Integer> weekList, int interval) {
        List<String> list = new ArrayList<>();
        try {
            String startStr = startTime + executeTime;
            String endStr = endTime + executeTime;
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-ddHH:mm");
            Date endDate = dateFormat.parse(endStr);
            Date startDate = dateFormat.parse(startStr);
            Date now = new Date();
            //设置日期过期,返回空
            if (now.getTime() > endDate.getTime()) {
                return new ArrayList<>();
            }
            interval++;
            for (Integer week : weekList) {
                String cronExpression = createCronStr(executeTime, week);
                if (StringUtils.isBlank(cronExpression)) {
                    continue;
                }

                Date startTime2 = getMonday(startDate);
                Date nextExecutionTime = getNextExecutionTime(cronExpression,startTime2);
                int add = 0;
                Date nownext = nextExecutionTime;
                while (nownext.getTime() <= endDate.getTime()) {
                    nownext = new Date(nextExecutionTime.getTime() + add * interval * 7 * 24 * 60 * 60 * 1000L);
                    SimpleDateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd HH:mm");
                    String str = dateFormat2.format(nownext);
                    if (nownext.getTime() <= endDate.getTime() && nownext.getTime()>=startDate.getTime())  {
                        list.add(str);
                    }
                    add++;
                }

            }
            Collections.sort(list);
        } catch (ParseException e) {
            System.out.println("解析异常: " + e.getMessage());
            e.printStackTrace();

        }
        return list;
    }

五、测试

计算2024-06-15到2026-12-31,每周一、四、六的20:40,并隔一周执行一次的所有执行时间

java 复制代码
public static void main(String[] args) {
        List<Integer> week = new ArrayList<>();
        week.add(1);
        week.add(4);
        week.add(6);
        long start = System.currentTimeMillis();
        List<String> list = getExecuteTimeList("2024-06-15", "2026-12-31", "20:40", week, 1);
        long end = System.currentTimeMillis();

        System.out.println(end - start + " ms");
        for(String element : list) {
            System.out.println(element);
        }
    }

六、测试结果

powershell 复制代码
下次执行时间: Mon Jun 10 20:40:00 CST 2024
下次执行时间: Thu Jun 13 20:40:00 CST 2024
下次执行时间: Sat Jun 15 20:40:00 CST 2024
74 ms
2024-06-15 20:40
2024-06-24 20:40
2024-06-27 20:40
2024-06-29 20:40
2024-07-08 20:40
2024-07-11 20:40
2024-07-13 20:40
2024-07-22 20:40
2024-07-25 20:40
2024-07-27 20:40
2024-08-05 20:40
2024-08-08 20:40
2024-08-10 20:40
2024-08-19 20:40
2024-08-22 20:40
2024-08-24 20:40
2024-09-02 20:40
2024-09-05 20:40
2024-09-07 20:40
2024-09-16 20:40
2024-09-19 20:40
2024-09-21 20:40
2024-09-30 20:40
2024-10-03 20:40
2024-10-05 20:40
2024-10-14 20:40
2024-10-17 20:40
2024-10-19 20:40
2024-10-28 20:40
2024-10-31 20:40
2024-11-02 20:40
2024-11-11 20:40
2024-11-14 20:40
2024-11-16 20:40
2024-11-25 20:40
2024-11-28 20:40
2024-11-30 20:40
2024-12-09 20:40
2024-12-12 20:40
2024-12-14 20:40
2024-12-23 20:40
2024-12-26 20:40
2024-12-28 20:40
2025-01-06 20:40
2025-01-09 20:40
2025-01-11 20:40
2025-01-20 20:40
2025-01-23 20:40
2025-01-25 20:40
2025-02-03 20:40
2025-02-06 20:40
2025-02-08 20:40
2025-02-17 20:40
2025-02-20 20:40
2025-02-22 20:40
2025-03-03 20:40
2025-03-06 20:40
2025-03-08 20:40
2025-03-17 20:40
2025-03-20 20:40
2025-03-22 20:40
2025-03-31 20:40
2025-04-03 20:40
2025-04-05 20:40
2025-04-14 20:40
2025-04-17 20:40
2025-04-19 20:40
2025-04-28 20:40
2025-05-01 20:40
2025-05-03 20:40
2025-05-12 20:40
2025-05-15 20:40
2025-05-17 20:40
2025-05-26 20:40
2025-05-29 20:40
2025-05-31 20:40
2025-06-09 20:40
2025-06-12 20:40
2025-06-14 20:40
2025-06-23 20:40
2025-06-26 20:40
2025-06-28 20:40
2025-07-07 20:40
2025-07-10 20:40
2025-07-12 20:40
2025-07-21 20:40
2025-07-24 20:40
2025-07-26 20:40
2025-08-04 20:40
2025-08-07 20:40
2025-08-09 20:40
2025-08-18 20:40
2025-08-21 20:40
2025-08-23 20:40
2025-09-01 20:40
2025-09-04 20:40
2025-09-06 20:40
2025-09-15 20:40
2025-09-18 20:40
2025-09-20 20:40
2025-09-29 20:40
2025-10-02 20:40
2025-10-04 20:40
2025-10-13 20:40
2025-10-16 20:40
2025-10-18 20:40
2025-10-27 20:40
2025-10-30 20:40
2025-11-01 20:40
2025-11-10 20:40
2025-11-13 20:40
2025-11-15 20:40
2025-11-24 20:40
2025-11-27 20:40
2025-11-29 20:40
2025-12-08 20:40
2025-12-11 20:40
2025-12-13 20:40
2025-12-22 20:40
2025-12-25 20:40
2025-12-27 20:40
2026-01-05 20:40
2026-01-08 20:40
2026-01-10 20:40
2026-01-19 20:40
2026-01-22 20:40
2026-01-24 20:40
2026-02-02 20:40
2026-02-05 20:40
2026-02-07 20:40
2026-02-16 20:40
2026-02-19 20:40
2026-02-21 20:40
2026-03-02 20:40
2026-03-05 20:40
2026-03-07 20:40
2026-03-16 20:40
2026-03-19 20:40
2026-03-21 20:40
2026-03-30 20:40
2026-04-02 20:40
2026-04-04 20:40
2026-04-13 20:40
2026-04-16 20:40
2026-04-18 20:40
2026-04-27 20:40
2026-04-30 20:40
2026-05-02 20:40
2026-05-11 20:40
2026-05-14 20:40
2026-05-16 20:40
2026-05-25 20:40
2026-05-28 20:40
2026-05-30 20:40
2026-06-08 20:40
2026-06-11 20:40
2026-06-13 20:40
2026-06-22 20:40
2026-06-25 20:40
2026-06-27 20:40
2026-07-06 20:40
2026-07-09 20:40
2026-07-11 20:40
2026-07-20 20:40
2026-07-23 20:40
2026-07-25 20:40
2026-08-03 20:40
2026-08-06 20:40
2026-08-08 20:40
2026-08-17 20:40
2026-08-20 20:40
2026-08-22 20:40
2026-08-31 20:40
2026-09-03 20:40
2026-09-05 20:40
2026-09-14 20:40
2026-09-17 20:40
2026-09-19 20:40
2026-09-28 20:40
2026-10-01 20:40
2026-10-03 20:40
2026-10-12 20:40
2026-10-15 20:40
2026-10-17 20:40
2026-10-26 20:40
2026-10-29 20:40
2026-10-31 20:40
2026-11-09 20:40
2026-11-12 20:40
2026-11-14 20:40
2026-11-23 20:40
2026-11-26 20:40
2026-11-28 20:40
2026-12-07 20:40
2026-12-10 20:40
2026-12-12 20:40
2026-12-21 20:40
2026-12-24 20:40
2026-12-26 20:40

Process finished with exit code 0

最终代码:

java 复制代码
import org.apache.commons.lang.StringUtils;
import org.quartz.CronExpression;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author dume
 * @ClassName CronUtils
 * @description: TODO
 * @date 2024年06月06日
 * @version: 1.0
 */
public class CronUtils {
    /**
     *
     * @param startTime  定时任务开始时间  yyyy-MM-dd
     * @param endTime    定时任务结束时间  yyyy-MM-dd
     * @param executeTime  执行时间 HH:mm
     * @param weekList   周几执行列表  [0,1,2,3,4,5,6] 代表:[周日,周一,周二,周三,周四,周五,周六]
     * @param interval   隔几周执行一次
     * @return
     */
    public static List<String> getExecuteTimeList(String startTime, String endTime, String executeTime, List<Integer> weekList, int interval) {
        List<String> list = new ArrayList<>();
        try {
            String startStr = startTime + executeTime;
            String endStr = endTime + executeTime;
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-ddHH:mm");
            Date endDate = dateFormat.parse(endStr);
            Date startDate = dateFormat.parse(startStr);
            Date now = new Date();
            //设置日期过期,返回空
            if (now.getTime() > endDate.getTime()) {
                return new ArrayList<>();
            }
            interval++;
            for (Integer week : weekList) {
                String cronExpression = createCronStr(executeTime, week);
                if (StringUtils.isBlank(cronExpression)) {
                    continue;
                }

                Date startTime2 = getMonday(startDate);
                Date nextExecutionTime = getNextExecutionTime(cronExpression,startTime2);
                int add = 0;
                Date nownext = nextExecutionTime;
                while (nownext.getTime() <= endDate.getTime()) {
                    nownext = new Date(nextExecutionTime.getTime() + add * interval * 7 * 24 * 60 * 60 * 1000L);
                    SimpleDateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd HH:mm");
                    String str = dateFormat2.format(nownext);
                    if (nownext.getTime() <= endDate.getTime() && nownext.getTime()>=startDate.getTime())  {
                        list.add(str);
                    }
                    add++;
                }

            }
            Collections.sort(list);
        } catch (ParseException e) {
            System.out.println("解析异常: " + e.getMessage());
            e.printStackTrace();

        }
        return list;
    }

    /**
     *计算cron表达式
     *@param executeTime  执行时间 HH:mm
     * @param week   周几
     * @return cron表达式
     * @throws ParseException
     */
    public static String createCronStr(String executeTime, Integer week)  {
        String weekStr = String.valueOf(week + 1);
        // 设置cron表达式,周三,下午3点30分执行
        String cronExpression = "0 %1$s %2$s ? * %3$s";
        String[] times = executeTime.split(":");
        String hour = times[0];
        String minute = times[1];
        return String.format(cronExpression, minute, hour, weekStr);
    }

    /**
     * 计算下次执行时间
     * @param cronExpression cron
     * @param startTime2  开始时间(开始时间的周一时间)
     * @return
     * @throws ParseException
     */
    public static  Date getNextExecutionTime(String cronExpression, Date startTime2) throws ParseException {
        CronExpression cron = new CronExpression(cronExpression);
        Date nextExecutionTime = cron.getNextValidTimeAfter(startTime2);

        System.out.println("下次执行时间: " + nextExecutionTime);
        return nextExecutionTime;
    }

    /**
     * 开始时间点的周一时间
     * @param startDate
     * @return
     */
    public static Date getMonday(Date startDate){
        /**
         * 计算给出时间的周一时间
         */
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(startDate);
        // 将小时、分钟、秒和毫秒字段设置为0
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        // 将日期设置为本周第一天(默认为周日)的前一天(即周一)
        calendar.add(Calendar.DAY_OF_WEEK, Calendar.MONDAY - calendar.get(Calendar.DAY_OF_WEEK));

        // 输出周一0点的时间
        return calendar.getTime();
    }

    public static void main(String[] args) {
        List<Integer> week = new ArrayList<>();
        week.add(1);
        week.add(4);
        week.add(6);
        long start = System.currentTimeMillis();
        List<String> list = getExecuteTimeList("2024-06-15", "2026-12-31", "20:40", week, 1);
        long end = System.currentTimeMillis();

        System.out.println(end - start + " ms");
        for(String element : list) {
            System.out.println(element);
        }
    }


}
相关推荐
Swift社区1 小时前
在 Swift 中实现字符串分割问题:以字典中的单词构造句子
开发语言·ios·swift
没头脑的ht1 小时前
Swift内存访问冲突
开发语言·ios·swift
没头脑的ht1 小时前
Swift闭包的本质
开发语言·ios·swift
wjs20241 小时前
Swift 数组
开发语言
吾日三省吾码2 小时前
JVM 性能调优
java
stm 学习ing2 小时前
FPGA 第十讲 避免latch的产生
c语言·开发语言·单片机·嵌入式硬件·fpga开发·fpga
Estar.Lee2 小时前
查手机号归属地免费API接口教程
android·网络·后端·网络协议·tcp/ip·oneapi
湫ccc3 小时前
《Python基础》之字符串格式化输出
开发语言·python
弗拉唐3 小时前
springBoot,mp,ssm整合案例
java·spring boot·mybatis