This is a creation in Article, where the information may have evolved or changed.
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 and 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's necessary t o re-verify Previous field//values)//The time of the next time each fetch is the last 1s t = t.add (1*time. Second-time. Duration (T.nanosecond ()) *time. nanosecond)//This flag indicates whether a field have been incremented.added: = false//If No time is found within five ye ARS, return Zero.yearlimit: = T.year () + 5wrap:if t.year () > Yearlimit {return time. time{}}//Find the first applicable month.//If it ' s this month and then does nothing. Approximation of the value by exponential method, and by constant approximation from sec to min to hour until day to Mon through 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 = Truet = 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<&L T;uint (T.hour ()) &s.hour = = 0 {if!added {added = Truet = 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 = Truet = T.truncate (t Ime. Minute)}t = T.add (1 * time. Minute) if t.minute () = = 0 {goto wrap}}for 1<<uint (T.second ()) &s.second = = 0 {if!added {added = Truet = T.trunca Te (time. Second)}t = T.add (1 * time. Second) if t.second () = = 0 {goto Wrap}}return t}
The most classic of the code is this bit operation:
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的更新