您的位置:首页 > 编程语言 > Go语言

go的cron里面经典的取下一次时间

2018-06-01 02:07 295 查看
func (s *SpecSchedule) Next(t time.Time) time.Time {
// General approach:
// For Month, Day, Hour, Minute, Second:
// Check if the time value matches.  If yes, continue to the next field.
// If the field doesn't match the schedule, then increment the field until it matches.
// While incrementing the field, a wrap-around brings it back to the beginning
// of the field list (since it is necessary to re-verify previous field
// values)

// 下一次每次取最近1s的时间
t = t.Add(1*time.Second - time.Duration(t.Nanosecond())*time.Nanosecond)

// This flag indicates whether a field has been incremented.
added := false

// If no time is found within five years, return zero.
yearLimit := t.Year() + 5

WRAP:
if t.Year() > yearLimit {
return time.Time{}
}

// Find the first applicable month.
// If it's this month, then do nothing.
//通过指数法逼近值,并通过从sec到min到hour到day到mon到year的不断逼近
for 1<<uint(t.Month())&s.Month == 0 {
// If we have to add a month, reset the other parts to 0.
if !added {
added = true
// Otherwise, set the date at the beginning (since the current time is irrelevant).
t = time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, t.Location())
}
t = t.AddDate(0, 1, 0)

// Wrapped around.
if t.Month() == time.January {
goto WRAP
}
}

// Now get a day in that month.
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
}


代码里面最经典的还是这种位运算:

1<<uint(t.Month())&s.Month

//转化为计算公式为: 2^t.Month & s.Month
//比如t.Month = 3, s.Month = 4 2^t.Month = 8 > s.Month 并且此时与操作为0
//说明此时t.Month与s.Month差距不多,当t.Month=1的时候 2^t.Month = 2 此时与操作结果不为0
//当t.Month=2的时候 也是如此

//总结就是 2^t.Month > s.Month的时候操作结果为0,需要轮转到比它小很多的位置,
//然后Month的更新再依赖于下面的day的更新
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  CRON Go