用戶使用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;
}