cronexpr 定時任務解析器

anyanfei發表於2021-04-26

Golang | cronexpr 庫

簡介 什麼是 cronexpr:

cronexpr 是一個高階的 crontab 解析表示式的庫,用於解析比原生 crontab 更好強大的定時任務解析器,當然,這個包是不包含定時任務功能的

安裝

GO MOD 模式下,執行:

$ go get github.com/gorhill/cronexpr 

案例

這個庫實際上非常簡單,我這裡拿一個小的例子來展示一下

package main

import (
    "fmt"
    "github.com/gorhill/cronexpr"
    "log"
    "testing"
    "time"
)

func TestCron(t *testing.T) {
    _,nextTimeArr := CheckCrontabExpr("* * 10 * * * *")
    for _,v := range nextTimeArr{
        fmt.Println(v)
    }
}

func CheckCrontabExpr(crontabs string) (err error, nextTimeArr []string) {
    var nextTime []time.Time
    if _, err = cronexpr.Parse(crontabs); err != nil {
        log.Fatal(err)
        return err, nil
    }
    //返回當前crontab後的5次執行,n為次數
    nextTime = cronexpr.MustParse(crontabs).NextN(time.Now(), 5)
    for _, v := range nextTime {
        nextTimeArr = append(nextTimeArr, v.String())
    }
    return nil, nextTimeArr
}

上面的例子是列印這個 crontab 表示式 “* * 10 * * * *” 的後五次執行時間,結果如下:

=== RUN   TestCron
2021-04-27 10:00:00 +0800 CST
2021-04-27 10:00:01 +0800 CST
2021-04-27 10:00:02 +0800 CST
2021-04-27 10:00:03 +0800 CST
2021-04-27 10:00:04 +0800 CST
--- PASS: TestCron (0.01s)
PASS

由於這個 crontab 表示式的最小粒度是秒,所以我們如果要自己寫一個定時任務的話,可以用:

for{
    var now = time.now()
    nextDoCron := cronexpr.MustParse("* * 10 * * * *").Next(now)
    if cronJob.nextTime.Before(now) || cronJob.nextTime.Equal(now) 
    ......
    ......
    select {
        case <-time.NewTimer(1 * time.Second).C:
    }
}

這樣就只需要每秒檢查一次,nextDoCron 變數就是根據當前時間 time.now() 獲取到的下一次執行時間

判斷過期了或者剛好過期時,則執行 if 中的內容即可做到定時任務的功效

他的 crontab 表示式支援非常多的定義,這裡我寫個自己的總結:

/**
    建立時間:2020-07-08 11:18:24
    根據傳入的表示式,檢查表示式是否正確:

      欄位名       是否強制      支援的格式         支援的特殊格式
    ----------     ----------   --------------    --------------------
    Seconds        No           0-59              * / , -
    Minutes        Yes          0-59              * / , -
    Hours          Yes          0-23              * / , -
    Day of month   Yes          1-31              * / , - L W (L指最後last,若用L,表示月底,W指的是最近的工作日)
    Month          Yes          1-12 or JAN-DEC   * / , -
    Day of week    Yes          0-6 or SUN-SAT    * / , - L # (L指最後last,若用1L,表示本月最後一週的週一)
    Year           No           1970–2099         * / , -

    00 */10 08-19 * * * * * 從08點到19點每10分鐘執行一次
    2021-04-27 08:00:00 +0800 CST
    2021-04-27 08:10:00 +0800 CST
    2021-04-27 08:20:00 +0800 CST
    2021-04-27 08:30:00 +0800 CST
    2021-04-27 08:40:00 +0800 CST

    00 00 17 * * 1-5 * 我們公司點加班餐的定時任務推送訊息 週一到週五每天的17點推送一次
    2021-04-27 17:00:00 +0800 CST
    2021-04-28 17:00:00 +0800 CST
    2021-04-29 17:00:00 +0800 CST
    2021-04-30 17:00:00 +0800 CST
    2021-05-03 17:00:00 +0800 CST

*/

總結

cronexpr 庫實際上解決了我們自己去解析表示式的苦,我記得之前我用 PHP 寫過一版 crontab 表示式解析,那叫一個心驚膽戰,生怕自己寫錯造成生產事故,定時任務有很多種實現方式,這個庫只是為我們解決了最基本也是最關鍵的表示式解析,推薦給大家,可以看看原始碼喲~

還想了解更多嗎?

更多請檢視:https://github.com/gorhill/cronexpr

歡迎加入我們 GOLANG 中國社群:https://gocn.vip/

更多原創文章乾貨分享,請關注公眾號
  • cronexpr 定時任務解析器
  • 加微信實戰群請加微信(註明:實戰群):gocnio