解析定時任務獲取今日待執行任務

用戶使用Linux中的crontab工具定製定時任務,時間段的格式minute hour day month week

其中數字範圍如下(包含首尾兩個數字):
minute:分鐘,數字範圍0-59;
hour:小時,數字範圍0-23;
day:日期,數字範圍1-31;
month:月份,數字範圍1-12;
week:星期,數字範圍0-6,0代表星期天,1代表星期一(未考慮7也代表星期天)。

除了數字,還可以包含特殊符號:
“*”:代表所有取值範圍內的數字
“/”:代表每間隔多久
“-”:代表可以取兩個數字之間的值,包括兩個數字本身
“,”:代表取所有分開的離散數字

舉例:
0 11 * * 1-3 表示每週一到週三的早上11點
0 2-12/2,19 * * * 表示2點到12點之間每兩個小時和下午7點

/* 獲取今日待執行任務 */
@RequestMapping("getTodayUnexecutedTask")
@ResponseBody
public List<String> getTodayUnexecutedTask() {
    Calendar cal=Calendar.getInstance();
    // 2019-08-26 09:04 星期一
    int minute=cal.get(Calendar.MINUTE); // 4
    int hour=cal.get(Calendar.HOUR_OF_DAY); // 9
    int day=cal.get(Calendar.DATE); // 26
    int month=cal.get(Calendar.MONTH)+1; // 8
    int week=cal.get(Calendar.DAY_OF_WEEK)-1; // 1

    String nowTime=getTwoDigitTime(hour)+":"+getTwoDigitTime(minute); // 當前時間,格式爲HH:ss
    int[] nowDate={day,month,week};

    List<String> objs = new ArrayList<String>();
    syslogrecord.recordSysLog("Task","定時任務","查詢定時任務","");
    try {
        List<TaskBean> list = taskService.findAllTask(); // 查詢定時任務列表
        if(list!=null){
            for (TaskBean bean : list) {
                String[] runTimeSplit=bean.getRunTime().trim().split(" +"); // 將run-time用空格分隔

                if(runTimeSplit.length==2){ // 如果是單次執行,runTimeSplit格式爲23:00 2019-8-28,分隔後長度爲2
                    String[] date=runTimeSplit[1].split("-");
                    int m=Integer.parseInt(date[1]);
                    int d=Integer.parseInt(date[2]);
                    if(m==month&&d==day){ // 如果日期等於今天
                        if(runTimeSplit[0].compareTo(nowTime)>0){ // 如果時間在當前時間之後
                            objs.add(runTimeSplit[0]+" "+bean.getOa()+" "+bean.getType()+" "+bean.getJobName());
                        }
                    }
                    continue;
                }

                // 除單次執行外,其它定時任務的run-time格式均是linux定時任務的格式
                // Linux crontab定時任務的格式: [分] [小時] [日] [月] [周]
                boolean flag=true; // [日] [月] [周]是否是今天
                for(int i=2;i<runTimeSplit.length;i++){
                    if(!isContainNum(runTimeSplit[i],nowDate[i-2])){ // 如果[日] [月] [周]不對應今天,將flag置爲false
                        flag=false;
                        break;
                    }
                }
                if(flag){ // 如果[日] [月] [周]符合要求,再判斷該任務是否還未執行
                    // 解析[分] [小時]格式,分別得到數字組成的List
                    List<Integer> minutes = getNumList(runTimeSplit[0],59);
                    List<Integer> hours = getNumList(runTimeSplit[1],23);

                    // 將每個小時和每個分鐘數組合爲時間字符串,與當前時間進行對比
                    for (int i=0; i<minutes.size(); i++) {
                        String minuteStr=getTwoDigitTime(minutes.get(i));
                        for (int j=0; j<hours.size(); j++) {
                            String hourStr=getTwoDigitTime(hours.get(j));
                            String timeStr=hourStr+":"+minuteStr;

                            if(timeStr.compareTo(nowTime)>0) { // 如果時間在當前時間之後
                                objs.add(timeStr+" "+bean.getOa()+" "+bean.getType()+" "+bean.getJobName());
                            }
                        }
                    }
                }
            }
        }
        Collections.sort(objs); // 按時間先後順序排序
        return objs;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

/* 傳入int型小時或分鐘,返回兩位字符串 */
private String getTwoDigitTime(int num){
    if(num<10){
        return "0"+num;
    }else{
        return ""+num;
    }
}

/*
 *  定時任務除了數字,還可以包含特殊符號“* / - ,”
 *  *代表所有取值範圍內的數字,/代表每間隔多久,-代表可以取兩個數字之間的值,包括兩個數字本身,,代表取所有分開的離散數字
 *  參數str是“* / - ,”組成的字符串,用,分隔後,可能的情況有5種:*  * /3  2-10 2-10/3  純數字
 *  求參數num是否包含在這些符號表達的數字集合中
 */
private boolean isContainNum(String str,int num){
    boolean flag=false;

    String[] strByComma=str.split(",");
    for(int i=0;i<strByComma.length;i++) {
        if (strByComma[i].matches("\\d+")) { // 純數字
            if (Integer.parseInt(strByComma[i]) == num) {
                flag = true;
                break;
            }
        } else if (strByComma[i].equals("*")) { // *
            flag = true;
            break;
        } else if (strByComma[i].startsWith("*/")) { // */數字
            int divisor = Integer.parseInt(strByComma[i].split("/")[1]);
            if (num % divisor == 0) {
                flag = true;
                break;
            }
        } else if (strByComma[i].contains("-")) { // 數字-數字 或者 (數字-數字)/數字
            String[] nums = strByComma[i].split("[-|/]");
            int divisor=1;
            if(nums.length==3){ // (數字-數字)/數字
                divisor = Integer.parseInt(nums[2]);
            }
            int min = Integer.parseInt(nums[0]);
            int max = Integer.parseInt(nums[1]);
            if (num >= min && num <= max && (num-min)%divisor == 0) {
                flag = true;
                break;
            }
        }
    }
    return flag;
}

/*
 *  定時任務除了數字,還可以包含特殊符號“* / - ,”
 *  *代表所有取值範圍內的數字,/代表每間隔多久,-代表可以取兩個數字之間的值,包括兩個數字本身,,代表取所有分開的離散數字
 *  參數str是“* / - ,”組成的字符串,用,分隔後,可能的情況有5種:*  * /3  2-10 2-10/3  純數字
 *  參數maxValue是最大值,最小值默認爲0
 *  求每種情況的最小值、最大值和被除數,求出符合該範圍的整數列表
 */
private List<Integer> getNumList(String str,int maxValue) {
    List<Integer> objs = new ArrayList<Integer>();

    String[] strByComma=str.split(",");
    for(int i=0;i<strByComma.length;i++){
        int min=0;
        int max=0;
        int divisor=1; // 被除數默認是1

        if(strByComma[i].matches("\\d+")){ // 純數字
            min=Integer.parseInt(strByComma[i]);
            max=Integer.parseInt(strByComma[i]);
        }else if(strByComma[i].contains("*")){ // * 或者 */數字
            max=maxValue;
            if(strByComma[i].startsWith("*/")){ // */數字
                divisor=Integer.parseInt(strByComma[i].split("/")[1]);
            }
        }else if(strByComma[i].contains("-")) { // 數字-數字 或者 (數字-數字)/數字
            String[] num = strByComma[i].split("[-|/]");
            min = Integer.parseInt(num[0]);
            max = Integer.parseInt(num[1]);
            if (num.length == 3) { // (數字-數字)/數字
                divisor = Integer.parseInt(num[2]);
            }
        }

        for(int j=min;j<=max;j+=divisor){
            objs.add(j);
        }
    }
    return objs;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章