Quartz Cron Expressions 用法

介绍

Quartz 是一个JAVA的定时任务框架,其定时任务使用了Cron Expressions对定时任务进行配置。

格式

cron 表达式是由 6 或 7 位由空格分开的字段组成的。各个字段可以包含任何被允许的值,伴随着对应某个字段所允许的特殊字符的各种组合。各个字段如下:

字段名称 强制出现 允许的值 允许的特殊字符
0-59 ,-*/
0-59 ,-*/
0-23 ,-*/
日期 1-31 ,-*?/LW
1-12或者是 JAN-DEC ,-*/
星期 1-7或者是 SUN-SAT ,-*?/L#
空或者是1970-2099 ,-*/

很简单的 cron 表达式: ?
很复杂的,例如:0/5 14,18,3-39,52
? JAN,MAR,SEP MON-FRI 2002-2010

特殊字符

  • *(“所有的值”)-匹配某个字段内的所有的值。例如,在“分”字段中的“*”代表“每一分钟”。

  • ?(“没有特定的值”)-“?”只能用在“日期”和“星期”字段中,在其他字段中是不能用的。例如,我想要触发器在某个月的某一天(比如是 10 号)触发,但我不关注那天是星期几,我就可以把 “10” 放到“日期”字段中,把“?”放到“星期”字段中。结合下面的例子来清楚的说明 cron 表达式的使用方法。

  • -用来定义范围。例如,在时字段中的“10-12”意思是“10 点, 11 点和 12 点”。

  • ,用来定义追加的值(列表)。例如,在星期字段中的“MON,WED,FRI”意思是“星期一,星期三,星期五”。

  • /用来定义增量。例如,在秒字段中的“0/15”表示从0秒开始每隔15秒,就是“0 秒,15 秒,30 秒,45 秒,0 秒,15 秒……”。在分字段中的“5/15”表示从 5 分开始每隔 15 分,就是“5分,20分,35分,50分,5 分, 20分……”。也可以在”空字符之后定义/,例如/5等价于在/前面有个0,即/5 等价于 0/5 。在日期字段中的“1/3”的意思是“在某月的第 1 天开始每隔 3 天触发一次”。

  • L(“last”)-只允许在两个字段中出现 “L” ,但 “L” 在这两个字段中每处的含义却各不相同。例如,在日期字段中的 “L” 意思是月末,即一个月的最后一天- 1 月的 31,平年 2 月的 28。如果 “L” 出现在星期字段中,则表示 “7” 或 “SAT”,即星期六(在西方星期六是一周的最后一天)。但是在星期字段中的 “L” 出现在一个数字之后意思是“某个月的最后一个星期几”-例如“6L”意思是“某个月的最后一个星期五”。在使用“L”选项的时候最好不要再用列表、范围值,否则的话会得到令人迷惑的结果。

  • W(“weekday 工作日”)-用来定义距离给定某一天最近的一个工作日(星期一到星期五)。例如,在日期字段中定义了 “15W” 意思是“某个月中距离 15 号最近的一个工作日”。
    如果 15 号是星期六的话,触发器会在星期五即 14 号触发。如果 15 号是周日,触发器会在下周一即 16 号触发。如果 15 号是星期二的话,触发器会在星期二当天 15 号触发。然而,如果在日期字段中定义了
    “1W”,如果 1 号是星期六的话,触发器会在下个星期一即 3 号触发,它不会跳回到上个月去触发。“W” 只能定义在日期中字段中,并且在日期字段中只能定义单独的一天,不能定义一个范围或一个日期列表。
    “L” 和 “W” 还可以组合出现在日期字段中,即“LW”,表示“某个月的最后一个工作日”。

  • #用来定义“某个月的第 n 个星期几”,# 只允许出现在星期字段中。例如,在星期字段中的“6#3”表示“某个月的第 3 个星期 5”(6 表示星期 5 ,3 表示某个月的第 3 周)。另一个例子:“2#1”意思是“某个月的第一个周的星期一 ”。
    “4#5”意思是“某个月中第 5 周的星期三 ”。注意,# 后面只允许出现 1-5(一般来说一个月中最多只有 5 周,不知道有没有可能有 6 周)。如果定义“#5”,在某个月中的第五周没有五个工作日中的任何一天,那么触发器在当月就不会触发。补充:我在我本地试了下,在星期字段中定义
    “#5” 会报错,# 之前必须要有数字,不知道是因为我的版本低还是我误解了原文的意思,或者是原文中的“#5”意思是“1#5”、“2#5”、“3#5”、“4#5”、“5#5”、“6#5”、“7#5”中的一种,原文偷懒了下。

    月份和星期的英文单词是不区分大小写的。MON 和 mon 的含义是一样的,都表示是星期一 。

例子

下面是一些完整的例子:

表达式 含义
0 0 12 * * ? 每天中午 12:00整触发
0 15 10 ? * * 每个月的星期一到星期七的上午 10:15 分触发,其实就是每天的上午 10:15,它和 0 15 10 * * ? 是等价的
0 15 10 * * ? 每天上午 10:15 分触发
0 15 10 * * ? * 每天上午 10:15 分触发
0 15 10 * * ? 2005 2015 年的每天上午 10:15 分触发
0 * 14 * * ? 每天下午 2 点开始每隔 1 分钟触发一次,一直到下午 2:59 分之后结束。
0 0/5 14 * * ? 每天下午 2 点开始每隔 5 分钟触发一次,一直到下午 2:55 分之后结束。
0 0/5 14,18 * * ? 每天下午 2 点开始每隔 5 分钟触发一次,一直到下午 2:55 分之后结束。然后,每天下午 6 点开始每隔 5 分钟触发一次,一直到下午 6:55 分之后结束。
0 0-5 14 * * ? 每天下午 2 点开始每隔 1 分钟触发一次,一直到下午 2:05 分之后结束。
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 每月的第 3 周的星期五的上午 10:15 分触发一次。
0 11 11 11 11 ? 每年的 11 月 11 日上午 11:11 分触发一次。

注意日期和星期字段中的“*”和“?”的作用。
补充:日期和星期字段中不能同时出现 “?”,为什么呢?一个定时器最终必须落实到某一天的某时某分某秒,其中日期和星期都可以表示某一天,但其他字段却不能表示某一天,所以这两个字段必须指定一个字段,两个字段中都是“?”则无法指定是哪一天,所以语法上是不正确的。

注意

  • 暂时还不支持同时定义日期字段和星期字段(换句话说,日期字段和星期字段中必须有一者为“?”,但不能同时为“?”)。
  • 在晚上 12:00 到 1:00 之间设置触发时间应该注意-“夏令时”会引起跳过或重复触发,具体是跳过触发还是触发取决于时间是往快拨还是往慢拨。