cron表达式基础讲解

54次阅读

共计 3250 个字符,预计需要花费 9 分钟才能阅读完成。

初识 corn

corn 表达式是一个字符串,分为 6 或 7 个域,每个域都会代表一个含义。

语法格式
6 个域:second minute hour day month week
7 个域:second minute hour day month week year
由上可见,7 个域与 6 个域的语法只差了 year,一般情况下,我们使用 6 个域的结构。

corn 表达式结构

corn 从左到右(中间用空格隔开):秒 分 小时 月份中的日 月份 星期中的日期 年份

各个字段的含义

位置 时间域名 允许值 允许的特殊字符
1 0-59 ,   -   *   /
2 0-59 ,   -   *   /
3 小时 0-23 ,   -   *   /
4 1-31 ,   -   *   ?   /   L   W  C
5 0-12 ,   -   *   /  
6 星期 1-7 ,   -   *   ?  /   L   C   #
7 年(可选) 1970-2099 ,   -   *   /

代码示例

声明:本次的 cron 讲解结合了 springboot 框架。由于只是讲解 cron 表达式,所以就不在介绍 springboot 中如何使用 @Scheduled 注解的相关配置了
秒的位置允许值为 0-59,如果写 60,将会报错

/* 以下代码在 springboot 启动时会抛出异常 */
@Scheduled(cron="60 * * * * * ?")
public void executeSchedule() {//TODO}

异常信息:Range exceeds maximum (60) |’60’ in expression “60 ?”
意思就是说,表达式中的 60 已经超出了最大范围。

/* 每分钟的第 8 秒执行 */
@Scheduled(cron="8 * * * * ?")
public void executeSchedule() {//TODO}

以上表达式含义为:每分钟的第 8 秒执行 executeSchedule 方法。秒后面的时间域是分钟,*(星号)表示 每...,这里表示 每分钟
注意: 是每分钟的第 8 秒,不是每隔 8 秒

秒 + 分

/* 每小时的 20 分 8 秒时执行 */
@Scheduled(cron="8 20 * * * ?")
public void executeSchedule() {//TODO}

以上表达式含义为:每小时的第 20 分,第 8 秒执行 executeSchedule 方法。分钟后的时间域是小时,由于是 *(星号),所以代表每小时。

秒 + 分 + 小时

/* 每天中午 12 点 20 分 8 秒执行 */
@Scheduled(cron="8 20 12 * * ?")
public void executeSchedule() {//TODO}

以上表达式含义为:每天中午 12 点 20 分 8 秒执行 executeSchedule 方法。小时后的时间域是天,*(星号)表示每天。
注意:时间的范围是 0-23,即 24 时制。所以 12 表示中午 12 点,如果表示午夜 12 点,表达式应该为:cron=8 20 0 * * ?

秒 + 分 + 小时 + 日

/* 每月 31 号中午 12 点 20 分 8 秒执行 */
@Scheduled(cron="8 20 12 31 * ?")
public void executeSchedule() {//TODO}

以上表达式含义为:每个月的 31 号中午 12 点 20 分 8 秒执行 executeSchedule 方法。
注意:
1、如果某个月份中不包含 31 号,则不执行
2、如果表达式为 cron="8 20 12 31 4 ?",启动项目时将会报错:4 月份没有 31 号,此表达式永远都不会执行,所以月份与日要配合使用

秒 + 分 + 小时 + 日 + 月

/* 4 月 30 号中午 12 点 20 分 8 秒执行 */
@Scheduled(cron="8 20 12 30 4 ?")
public void executeSchedule() {//TODO}

以上表达式含义为:4 月 30 号中午 12 点 20 分 8 秒执行 executeSchedule 方法。

秒 + 分 + 小时 + 日 + 月 + 星期
星期域具有特殊性,它由 1-7 组成,1 表示星期日(一周的开始),7 表示星期六(一周的最后一天);星期的定义与日和月同时表示,有可能会有冲突。
例子:cron="8 20 12 30 4 3"
以上表达式,看着好像是 星期二 4 月 30 号 中午 12 点 20 分 8 秒 这个意思,但实际上并不一定,原因很简单,你怎么就知道 4 月 30 号正好是星期二呢?所以这样定义表达式是存在问题的,也就是说 星期 在某种程度上是有 冲突 的。所以一般要在 星期 之间作出 取舍 。即 定义了星期,就不定义日;定义了日,就不定义星期。不需要定义的时候使用 ? 占位,舍弃谁谁就用 ? 代替
例子:cron="8 20 12 ? 4 2"
以上表达式含义为:4 月份的每个星期 1 的中午 12 点 20 分 8 秒

特殊字符

  • 星号(*):可用在所有时间域中,表示对应时间域的每一个时刻。例如,用于分钟域时,表示每分钟
表达式 含义
cron=”8 20 12 * 4 ?” 4 月份每天中午 12 点 20 分 8 秒
cron=”8 * 18 * 4 ?” 4 月份每天下午 6 点的每分钟的第 8 秒
  • 问号(?):该字符只在 星期域 日期域 中使用,它通常指定为 无意义的值,相当于占位符
  • 减号(-):表达一个范围(range),如,用在 小时域 16-20 表示从 下午 4 点到晚上 8 点,即 16,17,18,19,20
表达式 含义
cron=”8 20 7-9 * 2 ?” 2 月份每天 7 点,8 点,9 点的 20 分 8 秒
  • 逗号(,):表示列表值,如,用在 星期域,“1,3,5”,表示星期日,星期二,星期四
表达式 含义
cron=”2,59 20 3 * 2 ?” 2 月份每天凌晨 3 点 20 分的第 2 秒和第 59 秒
  • 正斜杠(/):表达一个等步长序列,x 为起始值,y 为增量步长值。如在 分钟域 中使用0/25,表示 0,25,50 秒。也可以使用*/y,同等于0/y
表达式 含义
cron=”2,59 0/25 3 * 2 ?” 2 月份每天凌晨 3 点的第 2 秒和第 59 秒,3 点 25(0+25)分的第 2 秒和第 59 秒,3 点 50(25+25)分的第 2 秒和第 59 秒
cron=”* 15/20 14 * 2 ?” 2 月份每天下午 2 点 15 分的每一秒,3 点 35(15+20)分每一秒,3 点 55(35+20)分的每一秒
  • L:该字符只在 日期域 星期域 中使用,代表 Last 的意思,但它在两个域中的意义不同。
含义
日期 当前月份的最后一天,如 1 月 31 日,非闰年 2 月 28 日
星期 表示星期六,同等于 7。但如果出现在星期域中,而且在前面还有一个数值 X,则表示“这个月的最后 X 天”,例如:5L 表示该月的最后星期四
  • W:该字符只能出现在 日期域 中, 是对前导日期的修饰,表示离该日期最近的工作日。例如 12W 表示离该月 12 号 最近的 工作日 ,如果该月的12 号星期六 ,则匹配11 号星期五;如果12 号星期日 ,则匹配13 号星期一;如果12 号星期三 ,那结果就是 星期三 。但必须注意 关联的匹配日期不能够跨月 ,如指定1W, 如果 1 号星期六 ,那么结果就是 3 号星期一,而非上个月的最后的那天。W 只能指定单一日期,而不能指定日期范围。
  • LW 组合:在日期域可以使用 LW, 含义是 当月的最后一个工作日
  • 井号(#):该字符只能在 星期域 中使用,表示 当月某个工作日
表达式 含义
6#3 当月的第三个星期五(6 表示星期五,#3 表示当前的第三个)
4#5 当月的第五个星期三。假设当月没有第五个星期三,则忽略不触发
  • C: 该字符只在 日期域 星期域 中使用,代表 Calendar 的意思。意义为 计划所关联的日期 。如果日期没有被关联,则相当于日历中的所有日期。如。5C日期域 中就相当于 日历 5 日以后的第一天 1C星期域 中相当于 星期日后的第一天

cron 表达式对特殊字符的大小写不敏感,对代表星期的缩写英文大小写也不敏感。
cron 表达式在线生成器:http://cron.qqe2.com/

小例子

表达式 含义
@Scheduled(cron=”0 0 1 1 1 ?”) 每年 1 月 1 号的凌晨 1 点执行一次
@Scheduled(cron=”0 0 1 1 1,6 ?”) 1 月和 6 月的 1 号的凌晨 1 点执行一次
@Scheduled(cron=”0 0 1 1 1,4,7,10 ?”) 每个季度的第 1 个月的 1 号的凌晨 1 点执行一次
@Scheduled(cron=”0 0 1 1 * ?”) 每月 1 号凌晨 1 点执行一次
@Scheduled(cron=”0 0 1 *”) 每天凌晨 1 点执行一次

正文完
 0