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);
        }
    }


}
相关推荐
爱上语文几秒前
Java LeetCode每日一题
java·开发语言·leetcode
qq_273900231 分钟前
解析TMalign文本文件中的转换矩阵
python·生物信息学
bug菌23 分钟前
Java GUI编程进阶:多线程与并发处理的实战指南
java·后端·java ee
Манго нектар27 分钟前
JavaScript for循环语句
开发语言·前端·javascript
程序猿小D36 分钟前
第二百六十九节 JPA教程 - JPA查询OrderBy两个属性示例
java·开发语言·数据库·windows·jpa
阿华的代码王国44 分钟前
【JavaEE】——文件IO的应用
开发语言·python
satan–01 小时前
R语言的下载、安装及环境配置(Rstudio&VSCode)
开发语言·windows·vscode·r语言
电饭叔1 小时前
《python语言程序设计》2018版第8章19题几何Rectangle2D类(下)-头疼的几何和数学
开发语言·python
Eternal-Student1 小时前
everyday_question dq20240731
开发语言·arm开发·php
极客先躯1 小时前
高级java每日一道面试题-2024年10月3日-分布式篇-分布式系统中的容错策略都有哪些?
java·分布式·版本控制·共识算法·超时重试·心跳检测·容错策略