CronExpression 规则
字段 允许值 允许的特殊字符 秒 0-59 , - * / 分 0-59 , - * / 小时 0-23 , - * / 日期 1-31 , - * ? / L W C 月份 1-12 或者 JAN-DEC , - * / 星期 1-7 或者 SUN-SAT , - * ? / L C # 年(可选) 留空, 1970-2099 , - * / 表达式意义 "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 ? * 6#3" 每月的第三个星期五上午10:15触发
'*' 字符可以用于所有字段,在“分”字段中设为"*"表示"每一分钟"的含义。
'?' 字符可以用在“日”和“周几”字段. 它用来指定 '不明确的值'. 这在你需要指定这两个字段中的某一个值而不是另外一个的时候会被用
到。在后面的例子中可以看到其含义。
'-' 字符被用来指定一个值的范围,比如在“小时”字段中设为"10-12"表示"10点到12点".
',' 字符指定数个值。比如在“周几”字段中设为"MON,WED,FRI"表示"the days Monday, Wednesday, and Friday".
'/' 字符用来指定一个值的的增加幅度. 比如在“秒”字段中设置为"0/15"表示"第0, 15, 30, 和 45秒"。而 "5/15"则表示"第5, 20, 35, 和
50". 在'/'前加"*"字符相当于指定从0秒开始. 每个字段都有一系列可以开始或结束的数值。对于“秒”和“分”字段来说,其数值范围为0到
59,对于“小时”字段来说其为0到23, 对于“日”字段来说为0到31, 而对于“月”字段来说为1到12。"/"字段仅仅只是帮助你在允许的数值
范围内从开始"第n"的值。 因此 对于“月”字段来说"7/6"只是表示7月被开启而不是“每六个月”, 请注意其中微妙的差别。
'L'字符可用在“日”和“周几”这两个字段。它是"last"的缩写, 但是在这两个字段中有不同的含义。例如,“日”字段中的"L"表示"一个月
中的最后一天" —— 对于一月就是31号对于二月来说就是28号(非闰年)。而在“周几”字段中, 它简单的表示"7" or "SAT",但是如果在“
周几”字段中使用时跟在某个数字之后, 它表示"该月最后一个星期×" —— 比如"6L"表示"该月最后一个周五"。当使用'L'选项时,指定确定
的列表或者范围非常重要,否则你会被结果搞糊涂的。
'W' 可用于“日”字段。用来指定历给定日期最近的工作日(周一到周五) 。比如你将“日”字段设为"15W",意为: "离该月15号最近的工作日
"。因此如果15号为周六,触发器会在14号即周五调用。如果15号为周日, 触发器会在16号也就是周一触发。如果15号为周二,那么当天就会触
发。然而如果你将“日”字段设为"1W", 而一号又是周六, 触发器会于下周一也就是当月的3号触发,因为它不会越过当月的值的范围边界。'W'
字符只能用于“日”字段的值为单独的一天而不是一系列值的时候。
'L'和'W'可以组合用于“日”字段表示为'LW',意为"该月最后一个工作日"。
'#' 字符可用于“周几”字段。该字符表示“该月第几个周×”,比如"6#3"表示该月第三个周五( 6表示周五而"#3"该月第三个)。再比如:
"2#1" = 表示该月第一个周一而 "4#5" = 该月第五个周三。注意如果你指定"#5"该月没有第五个“周×”,该月是不会触发的。
'C' 字符可用于“日”和“周几”字段,它是"calendar"的缩写。 它表示为基于相关的日历所计算出的值(如果有的话)。如果没有关联的日
历, 那它等同于包含全部日历。“日”字段值为"5C"表示"日历中的第一天或者5号以后",“周几”字段值为"1C"则表示"日历中的第一天或者
周日以后"。
对于“月份”字段和“周几”字段来说合法的字符都不是大小写敏感的。
验证CronExpression表达式合法性的j函数 并非正则表达式
function cronValidate(cronExpression ){ //alert("校验函数的开始!"); var cronParams = cronExpression.split(" "); if (cronParams.length < 6 || cronParams.length > 7) { return false; } //CronTrigger cronTrigger = new CronTrigger(); //cronTrigger.setCronExpression( cronExpression ); if (cronParams[3] == "?" || cronParams[5]=="?") { //Check seconds param if (!checkSecondsField(cronParams[0])) { return false; } //Check minutes param if (!checkMinutesField(cronParams[1])) { return false; } //Check hours param if (!checkHoursField(cronParams[2])) { return false; } //Check day-of-month param if (!checkDayOfMonthField(cronParams[3])) { return false; } //Check months param if (!checkMonthsField(cronParams[4])) { return false; } //Check day-of-week param if (!checkDayOfWeekField(cronParams[5])) { return false; } //Check year param if (cronParams.length == 7) { if (!checkYearField(cronParams[6])) { return false; } } return true; } else { return false; } } function checkSecondsField(secondsField) { return checkField(secondsField, 0, 59); } function checkField(secondsField, minimal, maximal) { if (secondsField.indexOf("-") > -1 ) { var startValue = secondsField.substring(0, secondsField.indexOf( "-" )); var endValue = secondsField.substring(secondsField.indexOf( "-" ) + 1); if (!(checkIntValue(startValue, minimal, maximal, true) && checkIntValue(endValue, minimal, maximal, true))) { return false; } try { var startVal = parseInt(startValue, 10); var endVal = parseInt(endValue, 10); return endVal > startVal; } catch (e) { return false; } } else if (secondsField.indexOf(",") > -1) { return checkListField(secondsField, minimal, maximal); } else if (secondsField.indexOf( "/" ) > -1) { return checkIncrementField( secondsField, minimal, maximal ); } else if (secondsField.indexOf( "*" ) != -1) { return true; } else { return checkIntValue(secondsField, minimal, maximal); } } function checkIntValue(value, minimal, maximal, checkExtremity) { try { var val = parseInt(value, 10); //判断是否为整数 if (value == val) { if (checkExtremity) { if (val < minimal || val > maximal) { return false; } } return true; } return false; } catch (e) { return false; } } function checkMinutesField(minutesField) { return checkField(minutesField, 0, 59); } function checkHoursField(hoursField) { return checkField(hoursField, 0, 23); } function checkDayOfMonthField(dayOfMonthField) { if (dayOfMonthField == "?") { return true; } if (dayOfMonthField.indexOf("L") >= 0) { return checkFieldWithLetter(dayOfMonthField, "L", 1, 7, -1, -1); } else if ( dayOfMonthField.indexOf("W") >= 0) { return checkFieldWithLetter(dayOfMonthField, "W", 1, 31, -1, -1); } else if (dayOfMonthField.indexOf("C") >= 0) { return checkFieldWithLetter(dayOfMonthField, "C", 1, 31, -1, -1); } else { return checkField( dayOfMonthField, 1, 31 ); } } function checkMonthsField(monthsField) { /* monthsField = StringUtils.replace( monthsField, "JAN", "1" ); monthsField = StringUtils.replace( monthsField, "FEB", "2" ); monthsField = StringUtils.replace( monthsField, "MAR", "3" ); monthsField = StringUtils.replace( monthsField, "APR", "4" ); monthsField = StringUtils.replace( monthsField, "MAY", "5" ); monthsField = StringUtils.replace( monthsField, "JUN", "6" ); monthsField = StringUtils.replace( monthsField, "JUL", "7" ); monthsField = StringUtils.replace( monthsField, "AUG", "8" ); monthsField = StringUtils.replace( monthsField, "SEP", "9" ); monthsField = StringUtils.replace( monthsField, "OCT", "10" ); monthsField = StringUtils.replace( monthsField, "NOV", "11" ); monthsField = StringUtils.replace( monthsField, "DEC", "12" );*/ monthsField.replace("JAN", "1"); monthsField.replace("FEB", "2"); monthsField.replace("MAR", "3"); monthsField.replace("APR", "4"); monthsField.replace("MAY", "5"); monthsField.replace("JUN", "6"); monthsField.replace("JUL", "7"); monthsField.replace("AUG", "8"); monthsField.replace("SEP", "9"); monthsField.replace("OCT", "10"); monthsField.replace("NOV", "11"); monthsField.replace("DEC", "12"); return checkField(monthsField, 1, 31); } function checkDayOfWeekField(dayOfWeekField) { /* dayOfWeekField = StringUtils.replace( dayOfWeekField, "SUN", "1" ); dayOfWeekField = StringUtils.replace( dayOfWeekField, "MON", "2" ); dayOfWeekField = StringUtils.replace( dayOfWeekField, "TUE", "3" ); dayOfWeekField = StringUtils.replace( dayOfWeekField, "WED", "4" ); dayOfWeekField = StringUtils.replace( dayOfWeekField, "THU", "5" ); dayOfWeekField = StringUtils.replace( dayOfWeekField, "FRI", "6" ); dayOfWeekField = StringUtils.replace( dayOfWeekField, "SAT", "7" );*/ dayOfWeekField.replace("SUN", "1" ); dayOfWeekField.replace("MON", "2" ); dayOfWeekField.replace("TUE", "3" ); dayOfWeekField.replace("WED", "4" ); dayOfWeekField.replace("THU", "5" ); dayOfWeekField.replace("FRI", "6" ); dayOfWeekField.replace("SAT", "7" ); if (dayOfWeekField == "?") { return true; } if (dayOfWeekField.indexOf("L") >= 0) { return checkFieldWithLetter(dayOfWeekField, "L", 1, 7, -1, -1); } else if (dayOfWeekField.indexOf("C") >= 0) { return checkFieldWithLetter(dayOfWeekField, "C", 1, 7, -1, -1); } else if (dayOfWeekField.indexOf("#") >= 0) { return checkFieldWithLetter(dayOfWeekField, "#", 1, 7, 1, 5); } else { return checkField(dayOfWeekField, 1, 7); } } function checkYearField(yearField) { return checkField(yearField, 1970, 2099); } function checkFieldWithLetter(value, letter, minimalBefore, maximalBefore, minimalAfter, maximalAfter) { var canBeAlone = false; var canHaveIntBefore = false; var canHaveIntAfter = false; var mustHaveIntBefore = false; var mustHaveIntAfter = false; if (letter == "L") { canBeAlone = true; canHaveIntBefore = true; canHaveIntAfter = false; mustHaveIntBefore = false; mustHaveIntAfter = false; } if (letter == "W" || letter == "C") { canBeAlone = false; canHaveIntBefore = true; canHaveIntAfter = false; mustHaveIntBefore = true; mustHaveIntAfter = false; } if (letter == "#") { canBeAlone = false; canHaveIntBefore = true; canHaveIntAfter = true; mustHaveIntBefore = true; mustHaveIntAfter = true; } var beforeLetter = ""; var afterLetter = ""; if (value.indexOf(letter) >= 0 ) { beforeLetter = value.substring( 0, value.indexOf(letter)); } if (!value.endsWith(letter)) { afterLetter = value.substring( value.indexOf( letter ) + 1 ); } if (value.indexOf(letter) >= 0) { if (letter == value) { return canBeAlone; } if (canHaveIntBefore) { if (mustHaveIntBefore && beforeLetter.length == 0) { return false; } if (!checkIntValue(beforeLetter, minimalBefore, maximalBefore, true)){ return false; } } else { if (beforeLetter.length > 0 ) { return false; } } if (canHaveIntAfter) { if ( mustHaveIntAfter && afterLetter.length == 0 ) { return false; } if (!checkIntValue(afterLetter, minimalAfter, maximalAfter, true)) { return false; } } else { if (afterLetter.length > 0) { return false; } } } return true; } /* function checkIntValue(value, minimal, maximal) { return checkIntValue(value, minimal, maximal, true); } */ function checkIncrementField(value, minimal, maximal) { var start = value.substring(0, value.indexOf("/")); var increment = value.substring(value.indexOf("/") + 1); if (!("*" == start)) { return checkIntValue(start, minimal, maximal, true) && checkIntValue(increment, minimal, maximal, false); } else { return checkIntValue(increment, minimal, maximal, true); } } function checkListField(value, minimal, maximal ) { var st = value.split(","); var values = new Array(st.length); for(var j = 0; j < st.length; j++) { values[j] = st[j]; } var previousValue = -1; for (var i= 0; i < values.length; i++) { var currentValue = values[i]; if (!checkIntValue(currentValue, minimal, maximal, true)) { return false; } try { var val = parseInt(currentValue, 10); if (val <= previousValue) { return false; } else { previousValue = val; } } catch (e) { // we have always an int } } return true; }
