cron表達式基礎講解

初識 corn

corn 表達式是一個字符串,分爲 6 或 7 個域,每一個域都會表明一個含義。java

語法格式
6 個域:second minute hour day month week
7 個域:second minute hour day month week year
由上可見,7 個域與 6 個域的語法只差了 year,通常狀況下,咱們使用 6 個域的結構。spring

corn表達式結構

corn 從左到右(中間用空格隔開):秒 分 小時 月份中的日 月份 星期中的日期 年份express

各個字段的含義springboot

位置 時間域名 容許值 容許的特殊字符
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 已經超出了最大範圍。code

字符串

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

以上表達式含義爲:每分鐘的第 8 秒執行 executeSchedule方法。秒後面的時間域是分鐘,*(星號)表示每...,這裏表示每分鐘
注意:是每分鐘的第 8 秒,不是每隔 8 秒域名

秒 + 分io

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

以上表達式含義爲:每小時的第 20 分,第 8 秒執行 executeSchedule 方法。分鐘後的時間域是小時,因爲是 *(星號),因此表明每小時。table

秒 + 分 + 小時

/* 天天中午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 方法。
注意:
一、若是某個月份中不包含 31 號,則不執行
二、若是表達式爲 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表達式對特殊字符的大小寫不敏感,對錶明星期的縮寫英文大小寫也不敏感。

小例子

表達式 含義
@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點執行
相關文章
相關標籤/搜索