Cron Expressions



Cron Expressions(Cron 表达式)是用来展示时间集合的字符串。在不同的系统或者框架上,Cron Expressions 的标准会有所差异。对于 Quartz Cron Expressions 来说,它被用来配置 CronTrigger 实例,由空格隔开分7个子表达式:

  1. Seconds (秒):范围为0-59的整数,可出现, - * /四个字符;
  2. Minutes(分):范围为0-59的整数,可出现, - * /四个字符;
  3. Hours (时):范围为0-23的整数,可出现, - * /四个字符;
  4. Day-of-Month(日):范围为1-31的整数,需要注意所选月的总日数,可出现, - * /? L W C八个字符;
  5. Month(月):范围为0-11的整数,或者使用字符串JAN、FEB、MAR、APR、MAY、JUN、JUL、AUG、SEP、OCT、NOV 和 DEC。可出现, - * /四个字符;
  6. Day-of-Week (周几):范围为1-7 (1 为周日) ,或者使用字符串 SUN、MON、TUE、WED、THU、FRI 和 SAT。,可出现, - * /? L W C八个字符;
  7. Year (年,可选),可出现, - * /四个字符;

例如,Cron Expressions 字符串 0 0 12 ? * WED 表示“每个星期三的12点”。

其中表达式中特殊字符的含义为:

  • 通配符*可以被用来表示域中“每个”可能的值。因此在”Month”域中的*表示每个月,而在 Day-Of-Week 域中的*则表示“周中的每一天”。
  • /字符用来表示值的增量,例如, 如果分钟域中放入0/15,它表示“从0开始,每隔15分钟”,如果在分钟域中使用3/20,则表示“从第3分钟开始,每隔20分钟”或者另外相同的形式就是3,23,43
  • ?字符可以用在 day-of-month 及 day-of-week 域中,它用来表示“没有指定值”。这对于需要指定一个或者两个域的值而不需要对其他域进行设置来说相当有用。
  • L字符可以在 day-of-month 及 day-of-week 中使用,这个字符是”last”的简写,但是在两个域中的意义不同。例如,在 day-of-month 域中的L表示这个月的最后一天,即,一月的31日,非闰年的二月的28日。如果它用在 day-of-week 中,则表示7或者SAT。但是如果在 day-of-week 域中,这个字符跟在别的值后面,则表示”当月的最后的周XXX”。例如:”6L” 或者 “FRIL”都表示本月的最后一个周五。当使用L选项时,最重要的是不要指定列表或者值范围,否则会导致混乱。
  • W字符用来指定距离给定日最接近的周几(在 day-of-week 域中指定)。例如:如果你为 day-of-month 域指定为15W,则表示“距离月中15号最近的周几”。
  • #表示表示月中的第几个周几。例如:day-of-week 域中的6#3 或者 FRI#3表示“月中第三个周五”。

Cron Expressions(Cron 表达式)是用来展示时间集合的字符串。在不同的系统或者框架上,Cron Expressions 的标准会有所差异。对于 Quartz Cron Expressions 来说,它被用来配置 CronTrigger 实例,由空格隔开分7个子表达式:

  1. Seconds (秒):范围为0-59的整数,可出现, - * /四个字符;
  2. Minutes(分):范围为0-59的整数,可出现, - * /四个字符;
  3. Hours (时):范围为0-23的整数,可出现, - * /四个字符;
  4. Day-of-Month(日):范围为1-31的整数,需要注意所选月的总日数,可出现, - * /? L W C八个字符;
  5. Month(月):范围为0-11的整数,或者使用字符串JAN、FEB、MAR、APR、MAY、JUN、JUL、AUG、SEP、OCT、NOV 和 DEC。可出现, - * /四个字符;
  6. Day-of-Week (周几):范围为1-7 (1 为周日) ,或者使用字符串 SUN、MON、TUE、WED、THU、FRI 和 SAT。,可出现, - * /? L W C八个字符;
  7. Year (年,可选),可出现, - * /四个字符;

例如,Cron Expressions 字符串 0 0 12 ? * WED 表示“每个星期三的12点”。

其中表达式中特殊字符的含义为:

  • 通配符*可以被用来表示域中“每个”可能的值。因此在”Month”域中的*表示每个月,而在 Day-Of-Week 域中的*则表示“周中的每一天”。
  • /字符用来表示值的增量,例如, 如果分钟域中放入0/15,它表示“从0开始,每隔15分钟”,如果在分钟域中使用3/20,则表示“从第3分钟开始,每隔20分钟”或者另外相同的形式就是3,23,43
  • ?字符可以用在 day-of-month 及 day-of-week 域中,它用来表示“没有指定值”。这对于需要指定一个或者两个域的值而不需要对其他域进行设置来说相当有用。
  • L字符可以在 day-of-month 及 day-of-week 中使用,这个字符是”last”的简写,但是在两个域中的意义不同。例如,在 day-of-month 域中的L表示这个月的最后一天,即,一月的31日,非闰年的二月的28日。如果它用在 day-of-week 中,则表示7或者SAT。但是如果在 day-of-week 域中,这个字符跟在别的值后面,则表示”当月的最后的周XXX”。例如:”6L” 或者 “FRIL”都表示本月的最后一个周五。当使用L选项时,最重要的是不要指定列表或者值范围,否则会导致混乱。
  • W字符用来指定距离给定日最接近的周几(在 day-of-week 域中指定)。例如:如果你为 day-of-month 域指定为15W,则表示“距离月中15号最近的周几”。
  • #表示表示月中的第几个周几。例如:day-of-week 域中的6#3 或者 FRI#3表示“月中第三个周五”。

?的含义

官方文档上提到问号时是这样说的:

The '?' character is allowed for the day-of-month and day-of-week fields. It is used to specify 'no specific value'. This is useful when you need to specify something in one of the two fileds, but not the other. See the examples below for clarification.

大致意思是说:

问号(?)可以用在日期或星期字段,用来指明‘没有特定的值’,当你为这两个字段中的一个设定值的时候就会用到它。下面的例子中说明了这一点。

可是,在后面的例子中并没有明确说明这个问号到底起什么作用,于是我编程试验了一下,得出以下结论:

1、如官方文档解释的那样,问号(?)的作用是指明该字段‘没有特定的值’;

2、星号(*)和其它值,比如数字,都是给该字段指明特定的值,只不过用星号(*)代表所有可能值;

3、cronExpression对日期和星期字段的处理规则是它们必须互斥,即只能且必须有一个字段有特定的值,另一个字段必须是‘没有特定的值’;

4、问号(?)就是用来对日期和星期字段做互斥的。

基于以上结论就可以解释下列情况:

1、当星期和日期都为*或数字时,报错
Support for specifying both a day-of-week AND a day-of-month parameter is not implemented.

即两个字段不能都指明的特定的值,必须互斥。这里的*和数字是一样的,如果都指明特定的数字,也是报一样的错。

2、当星期和日期都为?时,报错
'?' can only be specfied for Day-of-Month -OR- Day-of-Week.

3. 当星期和日期有一个为数字另一个为*时,报错:

Support for specifying both a day-of-week AND a day-of-month parameter is not implemented.

即两个字段不能都‘没有特定的值’。

这个是Spring的实现,没有什么道理,Spring就是规定这两个字段必须这样互斥的设置。

这与UNIX的crontab设置不一样,crontab的规则是日期和星期中只要满足一个就触发,所以不存在互斥的问题。

例子

下面是几个常见的 Quartz Cron Expressions 例子:

  • 0 0/5 * * * ?: 每隔5分钟触发一次
  • 10 0/5 * * * ?: 在每分钟的10秒后每隔5分钟触发一次的表达式(例如. 10:00:10 am, 10:05:10等.)。
  • 0 30 10-13 ? * WED,FRI : 在每个周三和周五的 10:30,11:30,12:30 触发。
  • 0 0/30 8-9 5,20 * ?: 在每个月的5号、20号的8点和10点之间每隔半个小时触发一次且不包括10点,只是8:30,9:00和9:30的表达式。

有些日程需求可能过于复杂而不能用单个表达式表述,例如:9:00到10:00之间每隔5分钟触发一次,下午1:00到10点每隔20分钟触发一次。这个解决方案就是创建两个触发器,两个触发器都运行相同的任务。

下面是构建 CronTrigger 的例子:

导包:

1
2
3
import static org.quartz.TriggerBuilder.*;
import static org.quartz.CronScheduleBuilder.*;
import static org.quartz.DateBuilder.*:

实例化一个 CronTrigger,每天 10:42 定期触发:

1
2
3
4
5
trigger = newTrigger()
   .withIdentity( "trigger3" , "group1" )
   .withSchedule(dailyAtHourAndMinute( 10 , 42 ))
   .forJob(myJobKey)
   .build();

或者使用:

1
2
3
4
5
trigger = newTrigger()
     .withIdentity( "trigger3" , "group1" )
     .withSchedule(cronSchedule( "0 42 10 * * ?" ))
     .forJob(myJobKey)
     .build();

参考引用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值