CRON是什么?

Quartz官网CENTOS下的CRON服务及CRONTAB命令的区别

SpringBoot - 集成Quartz框架之Quartz简介(一)SpringBoot - 集成Quartz框架之常用配置(二)SpringBoot - 集成Quartz框架之具体步骤(三)SpringBoot - 集成Quartz框架之独立数据源(四)SpringBoot - 集成Quartz框架之常见问题(五)SpringBoot - 集成Quartz框架之@DisallowConcurrentExecution注解详解(六)

CRON表达式

CRON表达式是一个字符串,字符串由5个或6个空格隔开,分为6个或7个域,每一个域代表一个含义,表达如如下:

秒 分 时 天(day-of-month) 月 周(day-of-week) 年[可选]

java cron 每周月 cron每周日执行一次_java

java cron 每周月 cron每周日执行一次_字符串_02

常用示例

*/5 * * * * ?:每隔 5 秒执行一次
0 */1 * * * ?:每隔 1 分钟执行一次
0 0 2 1 * ? *:每月 1 日的凌晨 2 点执行一次
0 15 10 ? * MON-FRI:周一到周五每天上午 10:15 执行一次
0 15 10 ? * 6L 2002-2006:2002 年至 2006 年的每个月的最后一个星期五上午 10:15 执行一次
0 0 23 * * ?:每天 23 点执行一次
0 0 1 * * ?:每天凌晨 1 点执行一次
0 0 1 1 * ?:每月 1 日凌晨 1 点执行一次
0 0 23 L * ?:每月最后一天 23 点执行一次
0 0 1 ? * L:每周星期天凌晨 1 点执行一次
0 26,29,33 * * * ?:在 26 分、29 分、33 分执行一次
0 0 0,13,18,21 * * ?:每天的 0 点、13 点、18 点、21 点都执行一次
0 0 10,14,16 * * ?:每天上午 10 点,下午 2 点,4 点执行一次
0 0/30 9-17 * * ?:朝九晚五工作时间内每半小时执行一次
0 0 12 ? * WED:每个星期三中午 12 点执行一次
0 0 12 * * ?:每天中午 12 点执行一次
0 15 10 ? * *:每天上午 10:15 执行一次
0 15 10 * * ?:每天上午 10:15 执行一次
0 15 10 * * ? *:每天上午 10:15 执行一次
0 15 10 * * ? 2005:2005 年的每天上午 10:15 执行一次
0 * 14 * * ?:每天下午 2 点到 2:59 期间的每 1 分钟执行一次
0 0/5 14 * * ?:每天下午 2 点到 2:55 期间的每 5 分钟执行一次
0 0/5 14,18 * * ?:每天下午 2 点到 2:55 期间和下午 6 点到 6:55 期间的每 5 分钟执行一次
0 0-5 14 * * ?:每天下午 2 点到 2:05 期间的每 1 分钟执行一次
0 10,44 14 ? 3 WED:每年三月的星期三的下午 2:10 和 2:44 执行一次
0 15 10 ? * MON-FRI:周一至周五的上午 10:15 执行一次
0 15 10 15 * ?:每月 15 日上午 10:15 执行一次
0 15 10 L * ?:每月最后一日的上午 10:15 执行一次
0 15 10 ? * 6L:每月的最后一个星期五上午 10:15 执行一次
0 15 10 ? * 6L 2002-2005:2002 年至 2005 年的每月的最后一个星期五上午 10:15 执行一次
0 15 10 ? * 6#3:每月的第三个星期五上午 10:15 执行一次

翻译CRON表达式

import java.text.ParseException;
import java.util.Date;
import org.quartz.CronExpression;

/**
 * CRON表达式工具类
 * @author ROCKY
 */
public class CronUtils {
    /**
     * 返回一个布尔值代表一个给定的CRON表达式是否有效
     */
    public static boolean isValid(String cronExpression) {
        return CronExpression.isValidExpression(cronExpression);
    }

    /**
     * 返回一个字符串值, 表示该消息无效CRON表达式给出有效性
     */
    public static String getInvalidMessage(String cronExpression) {
        try {
            new CronExpression(cronExpression);
            return null;
        } catch (ParseException pe) {
            return pe.getMessage();
        }
    }

    /**
     * 返回下一个执行时间根据给定的CRON表达式
     */
    public static Date getNextExecution(String cronExpression) {
        try {
            CronExpression cron = new CronExpression(cronExpression);
            return cron.getNextValidTimeAfter(new Date(System.currentTimeMillis()));
        } catch (ParseException e) {
            throw new IllegalArgumentException(e.getMessage());
        }
    }

    /**
     * 将一个给定的CRON表达式翻译成中文
     */
    private final static String[] CRON_EXPRESSION_DOMAIN = new String[]{"秒", "分", "时", "日", "月", "周", "年"};
    public static String translate(String expression) {

        if (StringUtils.isEmpty(expression)) {
            return expression;
        }

        String[] expressions = expression.split(" ");

        StringBuffer result = new StringBuffer();
        if (expressions.length == 6 || expressions.length == 7) {
            // 1. 年
            if (expressions.length == 7) {
                String year = expressions[6];
                if ((!year.equals("*") && !year.equals("?"))) {
                    result.append(year).append(CRON_EXPRESSION_DOMAIN[6]);
                }
            }

            // 2. 月
            String months = expressions[4];
            if (!months.equals("*") && !months.equals("?")) {
                if (months.contains("/")) {
                    result.append("从").append(months.split("/")[0]).append("日开始")
                            .append(",每").append(months.split("/")[1]).append(CRON_EXPRESSION_DOMAIN[4]);
                } else {
                    if (result.toString().contains("-")) {
                        result.append("每年");
                    }
                    result.append(months).append(CRON_EXPRESSION_DOMAIN[4]);
                }
            }

            // 3. 周
            String dayOfWeek = expressions[5];
            if (!dayOfWeek.equals("*") && !dayOfWeek.equals("?")) {
                if (dayOfWeek.contains(",")) {// 多个数字,逗号隔开
                    result.append("每周的第").append(dayOfWeek).append(CRON_EXPRESSION_DOMAIN[3]);
                } else if (dayOfWeek.contains("L") && dayOfWeek.length() > 1) {// 1L-7L
                    String index = dayOfWeek.split("L")[0];
                    String name = Weeks.name(index);
                    result.append("每月最后一周的");
                    result.append(name);
                } else if (dayOfWeek.contains("-")) {
                    String[] split = dayOfWeek.split("-");
                    String one = Weeks.name(split[0]);
                    String two = Weeks.name(split[1]);
                    result.append("每周").append(one).append("到").append(two);
                } else if (dayOfWeek.contains("#")) {
                    String[] split = dayOfWeek.split("#");
                    // 前面数字表示周几
                    String index = split[0];
                    // 后面的数字表示每月的第几周(1-4)
                    String weekOfMonth = split[1];
                    String name = Weeks.name(index);
                    result.append("每月第").append(weekOfMonth).append(CRON_EXPRESSION_DOMAIN[5]).append("的").append(name);
                } else {
                    if ("L".equals(dayOfWeek)) {
                        // L表示每周的最后一天
                        dayOfWeek = "7";
                    }
                    result.append("每周的");
                    result.append(Weeks.name(dayOfWeek));
                }
            }
            // 4. 日
            String days = expressions[3];
            if (!days.equals("*") && !days.equals("?")) {
                if (days.contains("/")) {
                    result.append("每周从第").append(days.split("/")[0]).append("天开始")
                            .append(",每").append(days.split("/")[1]).append(CRON_EXPRESSION_DOMAIN[3]);
                } else if ("L".equals(days)) {
                    // L表示每月的最后一天
                    result.append("每月最后一天");
                } else if ("W".equals(days)) {
                    // TODO 关于W的处理
                    result.append(days);
                } else {
                    result.append("每月").append(days).append("日");
                }
            } else {
                if ((result.toString().length() == 0 || expressions.length == 7) && !result.toString().contains("星期")) { // 前面没有内容的话,拼接下
                    result.append("每").append(CRON_EXPRESSION_DOMAIN[3]);
                }
            }
            // 5. 时
            String hours = expressions[2];
            if (!hours.equals("*")) {
                if (hours.contains("/")) {
                    result.append(getHourMinuteSecond(hours, 24, 2));
                } else {
                    if (!(result.toString().length() > 0)) { // 对于 , 的情况,直接拼接
                        result.append("每天").append(hours).append(CRON_EXPRESSION_DOMAIN[2]);
                    } else {
                        result.append(hours).append(CRON_EXPRESSION_DOMAIN[2]);
                    }
                }
            }

            // 6. 分
            String minutes = expressions[1];
            if (!minutes.equals("*")) {
                if (minutes.contains("/")) {
                    result.append(getHourMinuteSecond(minutes, 60, 1));
                } else if (minutes.equals("0")) {
                } else if (minutes.contains("-")) {
                    String[] splitMinute = minutes.split("-");
                    result.append(splitMinute[0]).append(CRON_EXPRESSION_DOMAIN[1]).append("到").append(splitMinute[1])
                            .append(CRON_EXPRESSION_DOMAIN[1]).append("每分钟");
                } else {
                    result.append(minutes).append(CRON_EXPRESSION_DOMAIN[1]);
                }
            }

            // 7. 秒
            String seconds = expressions[0];
            if (!seconds.equals("*")) {
                if (seconds.contains("/")) {
                    result.append(getHourMinuteSecond(seconds, 60, 0));
                } else if (!seconds.equals("0")) {
                    result.append(seconds).append(CRON_EXPRESSION_DOMAIN[0]);
                }
            }
            if (result.toString().length() > 0) {
                result.append("执行一次");
            }
        }
        return result.toString();
    }


    private static String getHourMinuteSecond(String time, int length, int index) {
        StringBuffer result = new StringBuffer();
        String[] split = time.split("/");
        String start = split[0];
        // 间隔
        String gap = split[1];
        String end = String.valueOf(length + (start.equals("*") ? 0 : Integer.parseInt(start)) - Integer.parseInt(gap));

        String unit1 = CRON_EXPRESSION_DOMAIN[index];
        String unit2 = CRON_EXPRESSION_DOMAIN[index];
        if (index == 1) {
            unit2 = "分钟";
        } else if (index == 2) {
            unit2 = "小时";
        }
        result.append("从").append(start.equals("*") ? 0 : Integer.parseInt(start)).append(unit1).append("开始").append("到").append(end)
                .append(unit1).append("范围内").append(",每隔").append(gap).append(unit2);
        return result.toString();
    }


    enum Weeks {
        SUN("1", "SUN", "星期天"),
        MON("2", "MON", "星期一"),
        TUE("3", "TUE", "星期二"),
        WED("4", "WED", "星期三"),
        THU("5", "THU", "星期四"),
        FRI("6", "FRI", "星期五"),
        SAT("7", "SAT", "星期六");

        private String index1;
        private String index2;
        private String name;

        Weeks(String index1, String index2, String name) {
            this.index1 = index1;
            this.index2 = index2;
            this.name = name;
        }

        public String getIndex1() {
            return index1;
        }

        public String getIndex2() {
            return index2;
        }

        public String getName() {
            return name;
        }

        public static String name(String index) {
            return Arrays.stream(Weeks.values()).filter(m -> m.getIndex1().equals(index) || m.getIndex2().equals(index)).map(m -> m.getName()).findFirst().get();
        }

    }


}