123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- package cron
- import "time"
- type SpecSchedule struct {
- Second, Minute, Hour, Dom, Month, Dow uint64
- }
- type bounds struct {
- min, max uint
- names map[string]uint
- }
- var (
- seconds = bounds{0, 59, nil}
- minutes = bounds{0, 59, nil}
- hours = bounds{0, 23, nil}
- dom = bounds{1, 31, nil}
- months = bounds{1, 12, map[string]uint{
- "jan": 1,
- "feb": 2,
- "mar": 3,
- "apr": 4,
- "may": 5,
- "jun": 6,
- "jul": 7,
- "aug": 8,
- "sep": 9,
- "oct": 10,
- "nov": 11,
- "dec": 12,
- }}
- dow = bounds{0, 6, map[string]uint{
- "sun": 0,
- "mon": 1,
- "tue": 2,
- "wed": 3,
- "thu": 4,
- "fri": 5,
- "sat": 6,
- }}
- )
- const (
-
- starBit = 1 << 63
- )
- func (s *SpecSchedule) Next(t time.Time) time.Time {
-
-
-
-
-
-
-
-
- t = t.Add(1*time.Second - time.Duration(t.Nanosecond())*time.Nanosecond)
-
- added := false
-
- yearLimit := t.Year() + 5
- WRAP:
- if t.Year() > yearLimit {
- return time.Time{}
- }
-
-
- for 1<<uint(t.Month())&s.Month == 0 {
-
- if !added {
- added = true
-
- t = time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, t.Location())
- }
- t = t.AddDate(0, 1, 0)
-
- if t.Month() == time.January {
- goto WRAP
- }
- }
-
- for !dayMatches(s, t) {
- if !added {
- added = true
- t = time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location())
- }
- t = t.AddDate(0, 0, 1)
- if t.Day() == 1 {
- goto WRAP
- }
- }
- for 1<<uint(t.Hour())&s.Hour == 0 {
- if !added {
- added = true
- t = time.Date(t.Year(), t.Month(), t.Day(), t.Hour(), 0, 0, 0, t.Location())
- }
- t = t.Add(1 * time.Hour)
- if t.Hour() == 0 {
- goto WRAP
- }
- }
- for 1<<uint(t.Minute())&s.Minute == 0 {
- if !added {
- added = true
- t = t.Truncate(time.Minute)
- }
- t = t.Add(1 * time.Minute)
- if t.Minute() == 0 {
- goto WRAP
- }
- }
- for 1<<uint(t.Second())&s.Second == 0 {
- if !added {
- added = true
- t = t.Truncate(time.Second)
- }
- t = t.Add(1 * time.Second)
- if t.Second() == 0 {
- goto WRAP
- }
- }
- return t
- }
- func dayMatches(s *SpecSchedule, t time.Time) bool {
- var (
- domMatch bool = 1<<uint(t.Day())&s.Dom > 0
- dowMatch bool = 1<<uint(t.Weekday())&s.Dow > 0
- )
- if s.Dom&starBit > 0 || s.Dow&starBit > 0 {
- return domMatch && dowMatch
- }
- return domMatch || dowMatch
- }
|