-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathschedule.go
More file actions
109 lines (95 loc) · 2.58 KB
/
schedule.go
File metadata and controls
109 lines (95 loc) · 2.58 KB
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
package schedule
import "time"
// Schedule is the struct used to represent a set of retrievable time.Time structs.
type Schedule struct {
at []time.Time
crn *CronExpression
crnI *CronInstance
followingIndex int
}
// At creates a new schedule that produces the dates provided.
func At(at ...time.Time) *Schedule {
if len(at) == 0 {
panic("schedule: at least one time must be provided")
}
sch := &Schedule{
at: make([]time.Time, len(at)),
followingIndex: -1,
}
currentTime := time.Time{}
for i, t := range at {
if t.Before(currentTime) || t.Equal(currentTime) {
panic("schedule: time order provided is invalid")
}
sch.at[i] = t
currentTime = t
}
return sch
}
// In creates a new schedule that produces dates based on provided durations.
// The durations are added sequentially.
// Example: In(time.Second, time.Minute):
// date = time.Now().Add(time.Second);
// date = date.Add(time.Minute).
func In(in ...time.Duration) *Schedule {
if len(in) == 0 {
panic("schedule: at least one duration must be provided")
}
sch := &Schedule{
at: make([]time.Time, len(in)),
followingIndex: -1,
}
currentTime := time.Now()
for i, d := range in {
currentTime = currentTime.Add(d)
sch.at[i] = currentTime
}
return sch
}
// As creates a new schedule that produces dates based on the provided CronExpression.
// Example: As(Cron().EveryDay()):
// date = 00:00:00 of the following day;
// ...
func As(crn *CronExpression) *Schedule {
crnI := crn.NewInstance(time.Now())
if err := crnI.Next(); err != nil {
panic("schedule: invalid CronExpression provided")
}
return &Schedule{
crn: crn,
crnI: crnI,
}
}
// AddCron is used to setup a CronExpression that starts operating after the scheduled times pass.
// Example: In(time.Hour * 24 * 7).AddCron(Cron().EveryDay()):
// date = time.Now().Add(time.Hour * 24 * 7);
// date = 00:00:00 of the following day;
// ...
func (sch *Schedule) AddCron(crn *CronExpression) {
sch.crn = crn
}
// Next is used to determine the following date to be produced.
func (sch *Schedule) Next() error {
if sch.followingIndex < len(sch.at)-1 {
sch.followingIndex++
return nil
}
if sch.crn == nil {
return OutdatedError
}
if sch.crnI == nil {
sch.crnI = sch.crn.NewInstance(sch.at[sch.followingIndex])
sch.followingIndex++
}
return sch.crnI.Next()
}
// Following returns the determined following date.
func (sch *Schedule) Following() time.Time {
if sch.followingIndex < 0 {
return time.Time{}
}
if sch.followingIndex < len(sch.at) {
return sch.at[sch.followingIndex]
}
return sch.crnI.Following()
}