-
Notifications
You must be signed in to change notification settings - Fork 22
/
express.go
204 lines (188 loc) · 4.4 KB
/
express.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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
package task
import (
"strconv"
"strings"
"time"
)
const (
Max_WeekDay = 7 //max weekday value
Min_WeekDay = 0 //min weekday value
Max_Month = 12 //max month value
Min_Month = 1 //min month value
Max_Day = 31 //max day value
Min_Day = 1 //min day value
Max_Hour = 23 //max hour value
Min_Hour = 0 //min hour value
Max_Minute = 59 //max minute value
Min_Minute = 0 //min minute value
Max_Second = 59 //max second value
Min_Second = 0 //min second value
)
const (
ExpressType_WeekDay = "weekday"
ExpressType_Month = "month"
ExpressType_Day = "day"
ExpressType_Hour = "hour"
ExpressType_Minute = "minute"
ExpressType_Second = "second"
)
type ExpressSet struct {
timeMap map[int]int
expressType string
rawExpress string
}
func (e *ExpressSet) IsMatch(t time.Time) bool {
switch e.expressType {
case ExpressType_WeekDay:
_, ok := e.timeMap[int(t.Weekday())]
return ok
case ExpressType_Month:
_, ok := e.timeMap[int(t.Month())]
return ok
case ExpressType_Day:
_, ok := e.timeMap[int(t.Day())]
return ok
case ExpressType_Hour:
_, ok := e.timeMap[int(t.Hour())]
return ok
case ExpressType_Minute:
_, ok := e.timeMap[int(t.Minute())]
return ok
case ExpressType_Second:
_, ok := e.timeMap[int(t.Second())]
return ok
default:
return false
}
}
/*
parse express
maybe:
"*" "*\/5" "1,2,3,5-8"
*/
func parseExpress(express, expressType string) (times *ExpressSet) {
V_Max := 0
V_Min := 0
switch expressType {
case ExpressType_WeekDay:
V_Max = Max_WeekDay
V_Min = Min_WeekDay
case ExpressType_Month:
V_Max = Max_Month
V_Min = Min_Month
case ExpressType_Day:
V_Max = Max_Day
V_Min = Min_Day
case ExpressType_Hour:
V_Max = Max_Hour
V_Min = Min_Hour
case ExpressType_Minute:
V_Max = Max_Minute
V_Min = Min_Minute
case ExpressType_Second:
V_Max = Max_Second
V_Min = Min_Second
default:
return nil
}
times = &ExpressSet{timeMap: make(map[int]int), expressType: expressType, rawExpress: express}
//if contains "/", reset frequency
frequency := 1
var err error
if strings.Contains(express, "/") {
frequency, err = strconv.Atoi(subString(express, strings.Index(express, "/")+1, -1))
if err != nil {
return nil
}
express = subString(express, 0, strings.Index(express, "/"))
}
//if express like "*" or "*/5"
if express == "*" {
for i := V_Min; i <= V_Max; i = i + frequency {
times.timeMap[i] = i
}
} else {
//if express like "1,2,4,12-20" or "12-2"
//tops:if parse int failed, will be ignore
tmpVals := strings.Split(express, ",")
for i := 0; i < len(tmpVals); i++ {
val := tmpVals[i]
if val == "" {
continue
}
//if not exists "-", parse int and join to times
if !strings.Contains(val, "-") {
atoi, errAtoi := strconv.Atoi(val)
if errAtoi == nil {
if _, ok := times.timeMap[atoi]; !ok {
times.timeMap[atoi] = atoi
}
}
continue
}
//if exists "-",parse max and min
//tips:only deal first "-"
firstString := subString(val, 0, strings.Index(val, "-"))
lastString := subString(val, strings.Index(val, "-")+1, -1)
var first, last int
if first, err = strconv.Atoi(firstString); err != nil {
//转义失败,忽略
continue
}
if last, err = strconv.Atoi(lastString); err != nil {
//转义失败,忽略
continue
}
if last > V_Max || last < V_Min || first < V_Min || first > V_Max {
//转义失败,忽略
continue
}
//one loop, like 5-7
if last >= first {
for i := first; i <= last; i = i + frequency {
if _, ok := times.timeMap[i]; !ok {
times.timeMap[i] = i
}
}
}
//not one loop, like 12-2
if last < first {
for i := first; i <= V_Max; i = i + frequency {
if _, ok := times.timeMap[i]; !ok {
times.timeMap[i] = i
}
}
for i := V_Min; i <= last; i = i + frequency {
if _, ok := times.timeMap[i]; !ok {
times.timeMap[i] = i
}
}
}
}
}
//if type is weekday, change 7 to 0
if expressType == ExpressType_WeekDay {
if _, ok := times.timeMap[7]; ok {
delete(times.timeMap, 7)
//modify for #8
if _, ok := times.timeMap[0]; !ok {
times.timeMap[0] = 0
}
}
}
return times
}
func subString(str string, begin, end int) string {
rs := []rune(str)
length := len(rs)
if begin < 0 {
begin = 0
}
if begin >= length {
return ""
}
if end == -1 || end > length {
return string(rs[begin:])
}
return string(rs[begin:end])
}