Avoid reinventing the wheel. If there are some good libraries, we just use them directly, there is no need to do some duplicate work, if these libraries can not meet the needs, may be submitted pull request or clone them, enhance them, optimize them, the current premise is that you have to know them.

This article gives you some information about the time and similar linux cron function of the timing task library.

jinzhu/now

jinzhu has written some good Go libraries in addition to contributing gorm, jinzhu/now is one of them.

Currently, the Go standard library provides a library about time time, which can satisfy 80% of our scenarios, but for some special scenarios, it is troublesome to use the standard library, and the same is true for some other programming languages, the time-related functions in the standard library are not convenient to use in some special scenarios, jinzhu provides the now library to meet the needs of some special scenarios, it is particularly convenient to use.

The most important functions of this library I have divided into two categories.

  • functions that calculate the first and last day
  • parsing

Of course it also contains functions to find the four seasons, as well as functions to explicitly find Sunday-Monday (some countries and regions count Sunday as the beginning of the week, some count Monday as the beginning of the week), which is more rarely used, so we will not introduce it.

Functions to calculate the beginning and last moments

Given a time, you can get the moment this minute starts, the moment this hour starts, the moment this day starts, the moment this week starts, the moment this month starts, the moment this season starts, the moment this half year starts, the moment this year starts.

1
2
3
4
5
6
7
8
9
import "github.com/jinzhu/now"
time.Now() // 2013-11-18 17:51:49.123456789 Mon
now.BeginningOfMinute()        // 2013-11-18 17:51:00 Mon
now.BeginningOfHour()          // 2013-11-18 17:00:00 Mon
now.BeginningOfDay()           // 2013-11-18 00:00:00 Mon
now.BeginningOfWeek()          // 2013-11-17 00:00:00 Sun
now.BeginningOfMonth()         // 2013-11-01 00:00:00 Fri
now.BeginningOfQuarter()       // 2013-10-01 00:00:00 Tue
now.BeginningOfYear()          // 2013-01-01 00:00:00 Tue

Or the last moment of this minute of this moment, the last moment of this hour, the last moment of this day, the last moment of this week, the last moment of this month, the last moment of this season, the last moment of this half year, the last moment of this year.

1
2
3
4
5
6
7
8
9
now.EndOfMinute()              // 2013-11-18 17:51:59.999999999 Mon
now.EndOfHour()                // 2013-11-18 17:59:59.999999999 Mon
now.EndOfDay()                 // 2013-11-18 23:59:59.999999999 Mon
now.EndOfWeek()                // 2013-11-23 23:59:59.999999999 Sat
now.EndOfMonth()               // 2013-11-30 23:59:59.999999999 Sat
now.EndOfQuarter()             // 2013-12-31 23:59:59.999999999 Tue
now.EndOfYear()                // 2013-12-31 23:59:59.999999999 Tue
now.WeekStartDay = time.Monday // Set Monday as the first day of the week, default Sunday is the first day of the week
now.EndOfWeek()                // 2013-11-24 23:59:59.999999999 Sun

If you are asking for the start moment and end moment of the current hour, you can use the functions of the package, which provides convenient functions, such as the start moment of the current hour.

1
_ = time.BeginningOfHour()

Its source code is as follows.

1
2
3
func BeginningOfHour() time.Time {
    return With(time.Now()).BeginningOfHour()
}

You can also set a specific time zone, date format and whether the first day of the week starts on Monday or Sunday.

1
2
3
4
5
6
7
myConfig := &now.Config{
    WeekStartDay: time.Monday,
    TimeLocation: location,
    TimeFormats: []string{"2006-01-02 15:04:05"},
}
t := time.Date(2013, 11, 18, 17, 51, 49, 123456789, time.Now().Location()) // // 2013-11-18 17:51:49.123456789 Mon
myConfig.With(t).BeginningOfWeek()         // 2013-11-18 00:00:00 Mon

Date parsing

The date parsing method of the markup library is provided in the form of samples, such as 2006-01-02 15:04:05, this parsing method is rather special, often we need to check the help documentation to set the corresponding format correctly, and the parsing is not too good when the fault tolerance.

The jizhu/now library provides a fault-tolerant parsing that it iterates through the standard library’s time format and tries to parse it using one of those formats. It handles both traversals and regular expressions, so if you’re after performance and a more explicit date format, it’s good to use the standard library’s parsing, but if you’re not after extreme performance, this parsing can be very fault-tolerant, you don’t need to remember the format template, just enter a date string and it will parse it. (I think it could also do with an optimization that allows users to provide specific date format templates in addition to the date format provided by the standard library, and set the priority)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// Parse(string) (time.Time, error)
t, err := now.Parse("2017")                // 2017-01-01 00:00:00, nil
t, err := now.Parse("2017-10")             // 2017-10-01 00:00:00, nil
t, err := now.Parse("2017-10-13")          // 2017-10-13 00:00:00, nil
t, err := now.Parse("1999-12-12 12")       // 1999-12-12 12:00:00, nil
t, err := now.Parse("1999-12-12 12:20")    // 1999-12-12 12:20:00, nil
t, err := now.Parse("1999-12-12 12:20:21") // 1999-12-12 12:20:21, nil
t, err := now.Parse("10-13")               // 2013-10-13 00:00:00, nil
t, err := now.Parse("12:20")               // 2013-11-18 12:20:00, nil
t, err := now.Parse("12:20:13")            // 2013-11-18 12:20:13, nil
t, err := now.Parse("14")                  // 2013-11-18 14:00:00, nil
t, err := now.Parse("99:99")               // 2013-11-18 12:20:00, Can't parse string as time: 99:99
// MustParse must parse string to time or it will panic
now.MustParse("2013-01-13")             // 2013-01-13 00:00:00
now.MustParse("02-17")                  // 2013-02-17 00:00:00
now.MustParse("2-17")                   // 2013-02-17 00:00:00
now.MustParse("8")                      // 2013-11-18 08:00:00
now.MustParse("2002-10-12 22:14")       // 2002-10-12 22:14:00
now.MustParse("99:99")                  // panic: Can't parse string as time: 99:99

carbon

golang-module/carbon is a lightweight, semantic, developer-friendly golang time processing library with support for chaining calls, developed by gouguoyin.

It provides a very rich set of functions, which are broadly divided into several categories.

Create carbon instance

Depending on the parameters, there are many ways to create them, the following is just a list of a few ways to create them.

1
2
3
4
carbon.CreateFromTimestamp(0).ToString() // 1970-01-01 08:00:00 +0800 CST
carbon.CreateFromTimestampMilli(1649735755981).ToString() // 2022-04-12 11:55:55.981 +0800 CST
carbon.CreateFromDate(2020, 8, 5).ToString() // // 2020-08-05 13:14:15 +0800 CST
carbon.CreateFromTime(13, 14, 15).ToString() // 2020-08-05 13:14:15 +0800 CST

Interconvert with standard libraries.

1
2
3
4
// Convert time.Time to Carbon
carbon.Time2Carbon(time.Now())
// Convert Carbon to time.Time
carbon.Now().Carbon2Time()

Yesterday, today and tomorrow, as well as converting to strings, are some of the examples below.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// At this moment today.
fmt.Sprintf("%s", carbon.Now()) // 2020-08-05 13:14:15
carbon.Now().ToString() // 2020-08-05 13:14:15 +0800 CST
carbon.Now().ToDateTimeString() // 2020-08-05 13:14:15
// Today's date.
carbon.Now().ToDateString() // 2020-08-05
// Today's time.
carbon.Now().ToTimeString() // 13:14:15
// At this moment yesterday.
fmt.Sprintf("%s", carbon.Yesterday()) // 2020-08-04 13:14:15
carbon.Yesterday().ToString() // 2020-08-04 13:14:15 +0800 CST
// This moment of tomorrow.
fmt.Sprintf("%s", carbon.Tomorrow()) // 2020-08-06 13:14:15
carbon.Tomorrow().ToString() // 2020-08-06 13:14:15 +0800 CST
carbon.Tomorrow().ToDateTimeString() // 2020-08-06 13:14:15

Some string formatting examples.

1
2
3
4
5
6
7
8
// Outputs a datetime string.
carbon.Parse("2020-08-05T13:14:15.999999999+08:00").ToDateTimeString() // 2020-08-05 13:14:15
// Outputs a datetime string containing milliseconds.
carbon.Parse("2020-08-05T13:14:15.999999999+08:00").ToDateTimeMilliString() // 2020-08-05 13:14:15.999
// Outputs a datetime string with microseconds.
carbon.Parse("2020-08-05T13:14:15.999999999+08:00").ToDateTimeMicroString() // 2020-08-05 13:14:15.999999
// Outputs a datetime string with nanoseconds.
carbon.Parse("2020-08-05T13:14:15.999999999+08:00").ToDateTimeNanoString() // 2020-08-05 13:14:15.999999999

Parsing

The carbon parsing is done in a standard format or a template format, the standard format is as follows.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
carbon.Parse("now").ToString() // 2020-08-05 13:14:15 +0800 CST
carbon.Parse("yesterday").ToString() // 2020-08-04 13:14:15 +0800 CST
carbon.Parse("tomorrow").ToString() // 2020-08-06 13:14:15 +0800 CST
carbon.Parse("2020").ToString() // 2020-01-01 00:00:00 +0800 CST
carbon.Parse("2020-8").ToString() // 2020-08-01 00:00:00 +0800 CST
carbon.Parse("2020-08").ToString() // 2020-08-01 00:00:00 +0800 CST
carbon.Parse("2020-8-5").ToString() // 2020-08-05 00:00:00 +0800 CST
carbon.Parse("2020-8-05").ToString() // 2020-08-05 00:00:00 +0800 CST
carbon.Parse("2020-08-05").ToString() // 2020-08-05 00:00:00 +0800 CST
carbon.Parse("2020-08-05.999").ToString() // 2020-08-05 00:00:00.999 +0800 CST
carbon.Parse("2020-08-05.999999").ToString() // 2020-08-05 00:00:00.999999 +0800 CST
carbon.Parse("2020-08-05.999999999").ToString() // 2020-08-05 00:00:00.999999999 +0800 CST
carbon.Parse("2020-8-5 13:14:15").ToString() // 2020-08-05 13:14:15 +0800 CST
carbon.Parse("2020-8-05 13:14:15").ToString() // 2020-08-05 13:14:15 +0800 CST
carbon.Parse("2020-08-05T13:14:15.999999999+08:00").ToString() // 2020-08-05 13:14:15.999999999 +0800 CST
carbon.Parse("20200805").ToString() // 2020-08-05 00:00:00 +0800 CST
carbon.Parse("20200805131415.999999999+08:00").ToString() // 2020-08-05 13:14:15.999999999 +0800 CST

Template format:

1
2
3
4
carbon.ParseByFormat("2020|08|05 13|14|15", "Y|m|d H|i|s").ToDateTimeString() // 2020-08-05 13:14:15
carbon.ParseByFormat("It is 2020-08-05 13:14:15", "\\I\\t \\i\\s Y-m-d H:i:s").ToDateTimeString() // 2020-08-05 13:14:15
carbon.ParseByFormat("今天是 2020年08月05日13时14分15秒", "今天是 Y年m月d日H时i分s秒").ToDateTimeString() // 2020-08-05 13:14:15
carbon.ParseByFormat("2020-08-05 13:14:15", "Y-m-d H:i:s", carbon.Tokyo).ToDateTimeString() // 2020-08-05 14:14:15

Or Go standard library layout mode:

1
2
3
4
carbon.ParseByLayout("2020|08|05 13|14|15", "2006|01|02 15|04|05").ToDateTimeString() // 2020-08-05 13:14:15
carbon.ParseByLayout("It is 2020-08-05 13:14:15", "It is 2006-01-02 15:04:05").ToDateTimeString() // 2020-08-05 13:14:15
carbon.ParseByLayout("今天是 2020年08月05日13时14分15秒", "今天是 2006年01月02日15时04分05秒").ToDateTimeString() // 2020-08-05 13:14:15
carbon.ParseByLayout("2020-08-05 13:14:15", "2006-01-02 15:04:05", carbon.Tokyo).ToDateTimeString() // 2020-08-05 14:14:15

Start moment and end moment

Similar to the function of jizhu/now, to find the start and end points of a moment.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// Start of this century
carbon.Parse("2020-08-05 13:14:15").StartOfCentury().ToDateTimeString() // 2000-01-01 00:00:00
// End of this century
carbon.Parse("2020-08-05 13:14:15").EndOfCentury().ToDateTimeString() // 2999-12-31 23:59:59
// Start time of this era
carbon.Parse("2020-08-05 13:14:15").StartOfDecade().ToDateTimeString() // 2020-01-01 00:00:00
carbon.Parse("2021-08-05 13:14:15").StartOfDecade().ToDateTimeString() // 2020-01-01 00:00:00
carbon.Parse("2029-08-05 13:14:15").StartOfDecade().ToDateTimeString() // 2020-01-01 00:00:00
// End of this era
carbon.Parse("2020-08-05 13:14:15").EndOfDecade().ToDateTimeString() // 2029-12-31 23:59:59
carbon.Parse("2021-08-05 13:14:15").EndOfDecade().ToDateTimeString() // 2029-12-31 23:59:59
carbon.Parse("2029-08-05 13:14:15").EndOfDecade().ToDateTimeString() // 2029-12-31 23:59:59
// Start time of this year
carbon.Parse("2020-08-05 13:14:15").StartOfYear().ToDateTimeString() // 2020-01-01 00:00:00
// End of the year
carbon.Parse("2020-08-05 13:14:15").EndOfYear().ToDateTimeString() // 2020-12-31 23:59:59
// Start of the quarter
carbon.Parse("2020-08-05 13:14:15").StartOfQuarter().ToDateTimeString() // 2020-07-01 00:00:00
// End of the quarter
carbon.Parse("2020-08-05 13:14:15").EndOfQuarter().ToDateTimeString() // 2020-09-30 23:59:59
......
// Start time of this minute
carbon.Parse("2020-08-05 13:14:15").StartOfMinute().ToDateTimeString() // 2020-08-05 13:14:00
// End time of this minute
carbon.Parse("2020-08-05 13:14:15").EndOfMinute().ToDateTimeString() // 2020-08-05 13:14:59
// Start time of this second
carbon.Parse("2020-08-05 13:14:15").StartOfSecond().ToString() // 2020-08-05 13:14:15 +0800 CST
// End time of this second
carbon.Parse("2020-08-05 13:14:15").EndOfSecond().ToString() // 2020-08-05 13:14:15.999999999 +0800 CST

Time Travel

Provides the function of time shifting, increasing time or decreasing time to another point in time.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
// Three centuries later
carbon.Parse("2020-02-29 13:14:15").AddCenturies(3).ToDateTimeString() // 2320-02-29 13:14:15
// After three centuries (months do not overflow)
carbon.Parse("2020-02-29 13:14:15").AddCenturiesNoOverflow(3).ToDateTimeString() // 2320-02-29 13:14:15
......
// Three centuries later
carbon.Parse("2020-02-29 13:14:15").AddCenturies(3).ToDateTimeString() // 2320-02-29 13:14:15
// After three centuries (months do not overflow)
carbon.Parse("2020-02-29 13:14:15").AddCenturiesNoOverflow(3).ToDateTimeString() // 2320-02-29 13:14:15
......
// Three nanoseconds later
carbon.Parse("2020-08-05 13:14:15.222222222").AddNanoseconds(3).ToString() // 2020-08-05 13:14:15.222222225 +0800 CST
// One nanosecond later
carbon.Parse("2020-08-05 13:14:15.222222222").AddNanossecond().ToString() // 2020-08-05 13:14:15.222222223 +0800 CST
// Three nanoseconds ago
carbon.Parse("2020-08-05 13:14:15.222222222").SubNanosseconds(3).ToString() // 2020-08-05 13:14:15.222222219 +0800 CST
// One nanosecond ago
carbon.Parse("2020-08-05 13:14:15.222222222").SubNanossecond().ToString() // 2020-08-05 13:14:15.222222221 +0800 CST

Benevolent, some people like this fine-grained approach, quite good. But seeing so many methods that provide similar functionality, I would provide a method and then a second unit specified with an enum type so that a time shift is taken care of by a single method, which is easier to learn and maintain, for example I would design it like this:

1
2
carbon.Parse("2020-02-29 13:14:15").Add(3, carbon.Century)
carbon.Parse("2020-02-29 13:14:15").Add(3, carbon.Nano)

Time difference

Find the difference between two times, for example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
// How many years difference
carbon.Parse("2021-08-05 13:14:15").DiffInYears(carbon.Parse("2020-08-05 13:14:15")) // -1
// Difference in how many years (absolute value)
carbon.Parse("2021-08-05 13:14:15").DiffAbsInYears(carbon.Parse("2020-08-05 13:14:15")) // 1
...
// How many seconds difference
carbon.Parse("2020-08-05 13:14:15").DiffInSeconds(carbon.Parse("2020-08-05 13:14:14")) // -1
// How many seconds difference (absolute value)
carbon.Parse("2020-08-05 13:14:15").DiffAbsInSeconds(carbon.Parse("2020-08-05 13:14:14")) // 1
// Difference string
carbon.Now().DiffInString() // just now
carbon.Now().AddYearsNoOverflow(1).DiffInString() // -1 year
carbon.Now().SubYearsNoOverflow(1).DiffInString() // 1 year
// Difference string (absolute value)
carbon.Now().DiffAbsInString(carbon.Now()) // just now
carbon.Now().AddYearsNoOverflow(1).DiffAbsInString(carbon.Now()) // 1 year
carbon.Now().SubYearsNoOverflow(1).DiffAbsInString(carbon.Now()) // 1 year

Some time judgments

For example.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
carbon.Parse("0").IsZero() // true
carbon.Parse("0000-00-00 00:00:00").IsZero() // true
carbon.Parse("0").IsZero() // true
carbon.Parse("0000-00-00 00:00:00").IsZero() // true
// Whether it is a leap year
carbon.Parse("2020-08-05 13:14:15").IsLeapYear() // true
// Is it a long year
carbon.Parse("2020-08-05 13:14:15").IsLongYear() // true
// Is it January
carbon.Parse("2020-08-05 13:14:15").IsJanuary() // false
// Whether it is a leap year
carbon.Parse("2020-08-05 13:14:15").IsLeapYear() // true
// Is it a long year
carbon.Parse("2020-08-05 13:14:15").IsLongYear() // true
// Is it January
carbon.Parse("2020-08-05 13:14:15").IsJanuary() // false

Set a unit of time

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// Setting area
carbon.Parse("2020-07-05 13:14:15").SetLocale("en").DiffForHumans() // 1 month ago
carbon.Parse("2020-07-05 13:14:15").SetLocale("zh-CN").DiffForHumans() // 1 月前
// Set the year, month, day, hour, minute and second
carbon.Parse("2020-01-01").SetDateTime(2019, 2, 2, 13, 14, 15).ToString() // 2019-02-02 13:14:15 +0800 CST
carbon.Parse("2020-01-01").SetDateTime(2019, 2, 31, 13, 14, 15).ToString() // 2019-03-03 13:14:15 +0800 CST
// Set year, month, day, hour, minute, second, millisecond
carbon.Parse("2020-01-01").SetDateTimeMilli(2019, 2, 2, 13, 14, 15, 999).ToString() // 2019-02-02 13:14:15.999 +0800 CST
carbon.Parse("2020-01-01").SetDateTimeMilli(2019, 2, 31, 13, 14, 15, 999).ToString() // 2019-03-03 13:14:15.999 +0800 CST
// Set year, month, day, hour, minute, second, microsecond
carbon.Parse("2020-01-01").SetDateTimeMicro(2019, 2, 2, 13, 14, 15, 999999).ToString() // 2019-02-02 13:14:15.999999 +0800 CST
carbon.Parse("2020-01-01").SetDateTimeMicro(2019, 2, 31, 13, 14, 15, 999999).ToString() // 2019-03-03 13:14:15.999999 +0800 CST
// Set year, month, day, hour, minute, second, nanosecond
carbon.Parse("2020-01-01").SetDateTimeNano(2019, 2, 2, 13, 14, 15, 999999999).ToString() // 2019-02-02 13:14:15.999999999 +0800 CST
carbon.Parse("2020-01-01").SetDateTimeNano(2019, 2, 31, 13, 14, 15, 999999999).ToString() // 2019-03-03 13:14:15.999999999 +0800 CST

Get a unit of time

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// Get current area
carbon.Now().Locale() // en
carbon.Now().SetLocale("zh-CN").Locale() // zh-CN
// Get current horoscope
carbon.Now().Constellation() // Leo
carbon.Now().SetLocale("en").Constellation() // Leo
carbon.Now().SetLocale("zh-CN").Constellation() // 狮子座
// Get the current season
carbon.Now().Season() // Summer
carbon.Now().SetLocale("en").Season() // Summer
carbon.Now().SetLocale("zh-CN").Season() // 夏季

carbon also provides methods to get horoscopes, seasons, and lunar calendars, as well as support for designing json codecs and database date formats.

In general, carbon provides a very rich, babysitting approach that allows you to handle datetime without having to do extra work.

robfig/cron

When doing business development, we often set some timers, in some cases we use Ticker on it, but we want to do more detailed control of the timing tasks, we have to think of another way, the first thing that comes to mind is the Linux cron function, very flexible So there is a corresponding library in the Go ecosystem, here to introduce you to two.

robfig/cron is a timed task library compatible with the Linux cron format, and it also provides an extended format that supports second granularity settings, a format compatible with the well-known Java Tigger library, quartz. We present it in Linux cron format.

Although cron provides AddFunc, AddJob, Schedule, but the similarities, we generally use AddFunc to add timed tasks. The first parameter of AddFunc is a cron expression, and the second parameter is a function to be executed when the expression package defined in cron is triggered. An example of cron usage is as follows.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
c := cron.New()
c.AddFunc("30 * * * *", func() { fmt.Println("Runs at 30 minutes of each hour.") })
c.AddFunc("30 3-6,20-23 * * *", func() { fmt.Println("Runs daily from 3-6am, 8-11pm for 30 minutes.") })
c.AddFunc("CRON_TZ=Asia/Shanghai 30 04 * * *", func() { fmt.Println("Runs at 04:30 BST daily.") }) // If not specified, the time zone of the machine is used by default.
c.AddFunc("@hourly",      func() { fmt.Println("Runs every hour. Start after 1 hour.") })
c.AddFunc("@every 1h30m", func() { fmt.Println("Runs every hour and 30 minutes, starts at 1 hour and 30 minutes.") })
c.Start()
...
// Functions are executed asynchronously in their goroutines.
...
// You can safely add tasks during this period.
c.AddFunc("@daily", func() { fmt.Println("Daily execution") })
...
// You can check the status of the task.
inspect(c.Entries())
...
c.Remove(entryID) // Remove a task.
...
c.Stop()  // No further follow-up tasks will be performed.

cron’s format

Field Name Mandatory setting? Allowable values Allowed special characters
Minutes Yes 0-59 * / , -
Hours Yes 0-23 * / , -
Day of month Yes 1-31 * / , - ?
Month Yes 1-12 or JAN-DEC * / , -
Day of week Yes 0-6 or SUN-SAT * / , - ?

Wikipedia also describes the cron format:

1
2
3
4
5
6
7
8
9
# ┌───────────── minute (0 - 59)
# │ ┌───────────── hour (0 - 23)
# │ │ ┌───────────── day of the month (1 - 31)
# │ │ │ ┌───────────── month (1 - 12)
# │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday;
# │ │ │ │ │                                   7 is also Sunday on some systems)
# │ │ │ │ │
# │ │ │ │ │
# * * * * * <command to execute>

Special characters represent.

  • *: represents each value that satisfies this field.
  • /: represents for the number of steps in the time range, for example the first field */5 represents every 5 minutes, which is 5,10,15,20,25,30,35,40,45,50,55,00 minutes.
  • ,: represents a set of lists, for example the fifth field MON,WED,FRI represents that it will trigger every Monday, Wednesday and Friday.
  • -: represents a range, for example the second field 10-15 means it will be triggered at 10, 11, 12, 13, 14, 15 o’clock every day.
  • ?: can sometimes be in the third and fifth fields instead of *

Also this library provides predefined several forms.

Predefined Types Description Equivalent price equation
@yearly (or @annually) At zero hour on January 1st of every year 0 0 1 1 *
@monthly On the first day of the month at zero hour 0 0 1 * *
@weekly On the first day of the week at zero hour, which is Sunday at zero hour 0 0 * * 0
@daily (or @midnight) Runs daily at zero 0 0 * * *
@hourly Runs at the beginning of each hour 0 * * * *

go-co-op/gocron

go-co-op/gocron is another excellent library of timed tasks.

It provides rich examples, so it’s easy to get started and you can easily apply it to your projects. Its cron parsing uses the above robfig/cron library, and you can use the cron format to implement timed tasks:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
package main
import (
    "time"
    "github.com/go-co-op/gocron"
)
var task = func() {}
func main() {
    s := gocron.NewScheduler(time.UTC)
    _, _ = s.Cron("*/1 * * * *").Do(task) // Execute every minute.
    _, _ = s.Cron("0 1 * * *").Do(task)   // Runs daily at 1:00.
    _, _ = s.Cron("0 0 * * 6,0").Do(task) // Runs at 0:00 on weekends.
}

But it also provides other user-friendly settings. Not necessarily using cron configuration.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
s := gocron.NewScheduler(time.UTC)
s.Every(5).Seconds().Do(func(){ ... })
// Every 5 minutes
s.Every("5m").Do(func(){ ... })
// Every 5 days
s.Every(5).Days().Do(func(){ ... })
s.Every(1).Month(1, 2, 3).Do(func(){ ... })
// set time
s.Every(1).Day().At("10:30").Do(func(){ ... })
// set multiple times
s.Every(1).Day().At("10:30;08:00").Do(func(){ ... })
s.Every(1).Day().At("10:30").At("08:00").Do(func(){ ... })
// Schedule each last day of the month
s.Every(1).MonthLastDay().Do(func(){ ... })
// Or each last day of every other month
s.Every(2).MonthLastDay().Do(func(){ ... })
// cron expressions supported
s.Cron("*/1 * * * *").Do(task) // every minute
// Asynchronous execution to avoid tasks blocking the scheduler.
s.StartAsync()