Seven's blog

你不会找到路,除非你敢于迷路

0%

cron 表达式简介

cron 表达式的格式

cron 表达式的格式由 7 部分组成, 各个部分之间用空格隔开, 其中第七个部分为可选部分. 如:

* * * * * * (*), 其中, 括起来的部分表示可选.

我们把上面被空格隔开的 7 个部分称为 7 个 “域”, 每个 “域” 代表不同的含义. 分别为:

{秒} {分} {时} {日} {月} {周} {年}, 其中, {年} 可以为空.

各个域的取值如下:

取值范围 允许的特殊符号
0 - 59 , - * /
0 - 59 , - * /
0 - 23 , - * /
1 - 31 , - * / ? L C W
1 - 12 (JAN - DEC) , - * /
1 - 7 (SUN - SAT) , - * / ? L C #
[年] 1970 - 2099 (可留空) , - * /

特殊符号的含义

各个域都通用的特殊符号

  • , 表示列出枚举值, 用于匹配多个指定的值:

    所在的域的值是 1,3,6 表示: 在每分钟的第 1秒, 第 3 秒, 第 6 秒触发事件.

  • - 匹配一个特定的范围值:

    所在的域的值是 10-14 表示: 在每小时的第 10, 11, 12, 13, 14 分钟都会触发事件.

  • * 匹配该域的任意值:

    所在的域的值是 * 表示: 每小时都会触发事件.

  • / 表示间隔多久触发一次, / 左边是开始触发时间, 右边是间隔时长:

    所在的域的值是 5/10 表示: 从每个月的 5 日起, 每 10 天触发一次事件. 也就是每个月的第 5, 15, 25 天触发事件.

再看 两个域公用的特殊符号

  • ? 匹配该域的任意值:

    所在的域的值是 ? 表示: 每天都会触发事件.

  • L 表示 “最后 (Last)”, 表示该域的最后一个值:

    • 如果 L 这个域, 表示 每个月的最后一天;
    • 如果 L 这个域, 表示 每个月的最后一个周几; 如 6L 表示 某个月的最后一个周五;
  • C 这个符号比较特别, 用于关联一个日历. 说实话我也没有理解 C 的具体用法, 下面摘抄一个我觉得写得相对来说比较详细的解释:

    C字母只能用在域上,它是calendar的缩写.它表示为基于相关的日历所计算出的值(如果有的话).如果没有关联的日历,那么它就等同于包含全部的日历.比如在域上的4C表示这个月的第4天或之后日历中的第一天,比如在域上的1C表示这个月的第一周或之后日历中的第一天. 这个地方的日历表示的是Quartz中的Calendar对象. 它允许用户自定义一个日历出来,使用这个你就能创建一个排除所有节假日的日历了. 假设10号是放假.那么10C在你自定义的日历上就表示的11号 .

这个域特有的符号

  • W 表示工作日, 系统将在离指定日期的最近的工作日触发事件:

    • 所在的域的值为 5W , 表示 在距离某月 5 日最近的工作日触发事件:
      • 如果某月 5 日恰好是周一至周五中的某一天, 那么就在 “当月 5 日” 触发事件;
      • 如果某月 5 日是周六, 那么就在 “距离周六 (5 号) 最近的一个工作日” 触发事件, 也就是上个周五 (当月 4 号) 触发事件;
      • 如果某月 5 日是周日, 那么就在 “距离周日 (5 号) 最近的一个工作日” 触发事件, 也就是下个周一 (当月 6 号) 触发事件;
    • 另外, W 的最近寻找不会跨过月份, 如:
      • 1W 表示 在距离某月 1 号的最近一个工作日触发事件, 但如果当月 1 号恰好是周六, 那么此次事件不会跨到上个月执行, 只会在本月下周一执行, 也就是在当月 3 号触发事件;

这个域特有的符号

  • # 用于指定某个月的第几个星期几:

    6#3 表示某个月的第 3 个星期五(6 表示星期五).

其他

  • LW 可以在日期域中联合使用, LW 表示这个月最后一周的工作日.

补充

  1. 严格意义上来说:

    • 上面提到的 ““ 域应该叫做 “DayOfMonth“, 即 一个月中的第几天;
    • 上面提到的 ““ 域应该叫做 “DayOfWeek“, 即 一周中的第几天, 取值 “1 - 7“ 分别代表 “SUN - SAT“;
  2. *? 的区别:

    • * 可以用在所有的部分中;

    • ? 只能用在 “第四” 和 “第六” 部分, 即 DayOfMonthDayOfWeek 两部分. 这两个域的值是 互斥 的, 因此需要设置一个 ? 来表明不想设置的那个字段.

      如: 设定每个月的 20 日触发事件, 不管 20 日 到底是星期几, 则只能写作: 1 1 1 20 * ? , 其中 所在的域只能用 ? 而非 * , 因为*** 表示 不管周几都会触发事件**, 与意愿相违.

  3. Cron表达式对特殊字符的大小写不敏感, 对代表星期的缩写英文大小写也不敏感.

举例

Cron表达式 表示的含义
0 0 12 ** ? 每天12:00触发事件
0 15 10 ? ** 每天10:15触发事件
0 15 10 ** ? 每天10:15触发事件
0 15 10 ** ? * 每天10:15触发事件
0 15 10 ** ? 2005 2005年的每天10:15触发事件
0 14 * ? 每天14点开始触发,每分钟触发一次,14:59分结束
0 0/5 14 ** ? 每天14点开始触发到14:59分结束的每5分钟触发一次事件
0 0/5 14,18 ** ? 每天14点开始到14:59期间和18点到18:59期间的每5分钟触发一次事件
0 0-5 14 ** ? 每天14点到14:05期间的每1分钟触发一次事件
0 10,44 14 ? 3 WED 每年3月的星期三的14:10和14: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 每月的第三个星期五10:15触发一次事件

参考文献

  1. Cron表达式的详细用法 ——- 骄傲牛
  2. Cron表达式语法及注意 ——- wangjunjun2008
  3. cron 表达式 语法 ——- 神奇物种
  4. Cron表达式语法 ——- 翔妖除魔
微信公众号
扫码关注, 一起进步!