You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
195 lines
3.7 KiB
Go
195 lines
3.7 KiB
Go
package startimer
|
|
|
|
import (
|
|
"errors"
|
|
"strconv"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
var rpmonths = map[string]int{
|
|
"JAN": 1,
|
|
"FEB": 2,
|
|
"MAR": 3,
|
|
"APR": 4,
|
|
"MAY": 5,
|
|
"JUN": 6,
|
|
"JUL": 7,
|
|
"AUG": 8,
|
|
"SEP": 9,
|
|
"OCT": 10,
|
|
"NOV": 11,
|
|
"DEC": 12,
|
|
}
|
|
|
|
var rpweekdays = map[string]int{
|
|
"SUN": 0,
|
|
"MON": 1,
|
|
"TUE": 2,
|
|
"WED": 3,
|
|
"THU": 4,
|
|
"FRI": 5,
|
|
"SAT": 6,
|
|
}
|
|
|
|
func NewTimerWithCron(cron ...string) (StarTimer, error) {
|
|
tmr := StarTimer{
|
|
base: time.Now(),
|
|
nextDate: time.Time{},
|
|
mu: new(sync.RWMutex),
|
|
}
|
|
for _, c := range cron {
|
|
c = "0 " + c
|
|
rpt, err := parseCron(c)
|
|
if err != nil {
|
|
return tmr, err
|
|
}
|
|
tmr.repeat = append(tmr.repeat, rpt)
|
|
}
|
|
return tmr, nil
|
|
}
|
|
|
|
func NewTimerWithSecCron(cron ...string) (StarTimer, error) {
|
|
tmr := StarTimer{
|
|
base: time.Now(),
|
|
nextDate: time.Time{},
|
|
mu: new(sync.RWMutex),
|
|
}
|
|
for _, c := range cron {
|
|
rpt, err := parseCron(c)
|
|
if err != nil {
|
|
return tmr, err
|
|
}
|
|
tmr.repeat = append(tmr.repeat, rpt)
|
|
}
|
|
return tmr, nil
|
|
}
|
|
|
|
func parseCron(cron string) (*Repeats, error) {
|
|
{
|
|
cron = strings.ToUpper(cron)
|
|
for k, v := range rpmonths {
|
|
cron = strings.ReplaceAll(cron, k, strconv.Itoa(v))
|
|
}
|
|
for k, v := range rpweekdays {
|
|
cron = strings.ReplaceAll(cron, k, strconv.Itoa(v))
|
|
}
|
|
}
|
|
for {
|
|
oldLen := len(cron)
|
|
cron = strings.ReplaceAll(strings.TrimSpace(cron), " ", " ")
|
|
if len(cron) == oldLen {
|
|
break
|
|
}
|
|
}
|
|
ct := strings.Split(cron, " ")
|
|
if len(ct) != 6 {
|
|
return nil, errors.New("Invalid cron,argument not enough")
|
|
}
|
|
|
|
foundFirstAll := false
|
|
var myMap = make(map[Unit]map[uint32]Repeat)
|
|
for idx, c := range ct {
|
|
if _, ok := myMap[Unit(idx)]; !ok {
|
|
myMap[Unit(idx)] = make(map[uint32]Repeat)
|
|
}
|
|
var minVal, maxVal int
|
|
switch Unit(idx) {
|
|
case STAR_MINUTE, STAR_SECOND:
|
|
minVal = 0
|
|
maxVal = 60
|
|
case STAR_HOUR:
|
|
minVal = 0
|
|
maxVal = 24
|
|
case STAR_DAY:
|
|
minVal = 1
|
|
maxVal = 32
|
|
case STAR_MONTH:
|
|
minVal = 1
|
|
maxVal = 13
|
|
case STAR_WEEK:
|
|
minVal = 0
|
|
maxVal = 7
|
|
}
|
|
|
|
cdt := strings.Split(c, ",")
|
|
for _, dtl := range cdt {
|
|
dtl = strings.TrimSpace(dtl)
|
|
if dtl == "*" {
|
|
if !foundFirstAll {
|
|
foundFirstAll = true
|
|
if maxVal > 0 {
|
|
for i := minVal; i < maxVal; i++ {
|
|
val := uint32(i)
|
|
myMap[Unit(idx)][val] = Repeat{
|
|
Unit: Unit(idx),
|
|
Value: val,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
continue
|
|
}
|
|
if strings.Contains(dtl, "*/") {
|
|
num, err := strconv.Atoi(strings.TrimPrefix(dtl, "*/"))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for i := minVal; i < maxVal; i++ {
|
|
val := i
|
|
if Unit(idx) == STAR_DAY || Unit(idx) == STAR_MONTH {
|
|
val--
|
|
}
|
|
if val%num == 0 {
|
|
myMap[Unit(idx)][uint32(val)] = Repeat{
|
|
Unit: Unit(idx),
|
|
Value: uint32(i),
|
|
}
|
|
}
|
|
}
|
|
continue
|
|
}
|
|
if strings.Contains(dtl, "-") {
|
|
numbers := strings.Split(dtl, "-")
|
|
if len(numbers) != 2 {
|
|
return nil, errors.New("Invalid Cron")
|
|
}
|
|
startNum, err := strconv.Atoi(numbers[0])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
endNum, err := strconv.Atoi(numbers[1])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if startNum < minVal && endNum >= maxVal {
|
|
return nil, errors.New("Invalid Cron")
|
|
}
|
|
for i := startNum; i <= endNum; i++ {
|
|
myMap[Unit(idx)][uint32(i)] = Repeat{
|
|
Unit: Unit(idx),
|
|
Value: uint32(i),
|
|
}
|
|
}
|
|
continue
|
|
}
|
|
number, err := strconv.Atoi(dtl)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
myMap[Unit(idx)][uint32(number)] = Repeat{
|
|
Unit: Unit(idx),
|
|
Value: uint32(number),
|
|
}
|
|
}
|
|
}
|
|
var repeat Repeats
|
|
for _, v := range myMap {
|
|
for _, rpt := range v {
|
|
repeat.Repeat = append(repeat.Repeat, rpt)
|
|
}
|
|
}
|
|
return &repeat, nil
|
|
}
|