-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathschedule.go
124 lines (104 loc) · 2.19 KB
/
schedule.go
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// Copyright (c) 2019,CAO HONGJU. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package scheduler
import "time"
// Schedule describes a job's duty cycle.
type Schedule interface {
// Next returns the next activation time, later than the given time.
// Next returns 0(Time.IsZero()) to indicate job termination.
Next(time.Time) time.Time
}
// ScheduleFunc is an adapter to allow the use of ordinary functions as the Schedule interface.
type ScheduleFunc func(time.Time) time.Time
// Next returns the next activation time, later than the given time.
func (f ScheduleFunc) Next(t time.Time) time.Time {
return f(t)
}
// Union returns the new schedule that union left schedule and right schedule(left ∪ right).
func Union(l, r Schedule) Schedule {
return &union{
l: l,
r: r,
}
}
type union struct {
l Schedule
r Schedule
}
func (us *union) Next(t time.Time) time.Time {
t1 := us.l.Next(t)
t2 := us.r.Next(t)
if t1.IsZero() {
return t2
}
if t2.IsZero() {
return t1
}
if t1.Before(t2) {
return t1
}
return t2
}
// Minus returns the new schedule that the left schedule minus the right schedule(l - r).
func Minus(l, r Schedule) Schedule {
return &minus{
l: l,
r: r,
}
}
type minus struct {
l Schedule
r Schedule
}
func (ms *minus) Next(t time.Time) time.Time {
t1 := ms.l.Next(t)
t2 := ms.r.Next(t)
for {
if t2.IsZero() {
return t1
}
// t1 < t2
if t1.Before(t2) {
return t1
}
// t1 == t2, recalculated
// the trigger condition is not valid
if t1.Equal(t2) {
t1 = ms.l.Next(t1)
t2 = ms.r.Next(t2)
continue
}
for t1.After(t2) && !t2.IsZero() { // t1 > t2
t2 = ms.r.Next(t2)
}
}
}
// Intersect returns the intersection of left schedule and right schedule(l ∩ r).
func Intersect(l, r Schedule) Schedule {
return &intersect{
l: l,
r: r,
}
}
type intersect struct {
l Schedule
r Schedule
}
func (is *intersect) Next(t time.Time) time.Time {
t1 := is.l.Next(t)
t2 := is.r.Next(t)
for {
if t1.IsZero() || t2.IsZero() {
return t1
}
if t1.Equal(t2) { // valid
return t1
}
if t1.Before(t2) {
t1 = is.l.Next(t1)
} else {
t2 = is.r.Next(t2)
}
}
}