91 lines
1.7 KiB
Go
91 lines
1.7 KiB
Go
package pttodo
|
|
|
|
import (
|
|
"encoding/json"
|
|
"math"
|
|
"regexp"
|
|
"strconv"
|
|
"time"
|
|
|
|
cron "github.com/robfig/cron/v3"
|
|
)
|
|
|
|
type Schedule string
|
|
|
|
func (schedule Schedule) MarshalJSON() ([]byte, error) {
|
|
return json.Marshal(string(schedule))
|
|
}
|
|
|
|
func (schedule *Schedule) UnmarshalJSON(b []byte) error {
|
|
return json.Unmarshal(b, (*string)(schedule))
|
|
}
|
|
|
|
func (schedule Schedule) Next(t time.Time) (time.Time, error) {
|
|
scheduler := schedulerFactory(string(schedule))
|
|
return scheduler.next(t)
|
|
}
|
|
|
|
type scheduler interface {
|
|
next(time.Time) (time.Time, error)
|
|
}
|
|
|
|
func schedulerFactory(s string) scheduler {
|
|
if s == "" {
|
|
return scheduleNever{}
|
|
} else if scheduleDurationPattern.MatchString(s) {
|
|
return scheduleDuration(s)
|
|
} else if scheduleDuePattern.MatchString(s) {
|
|
n, _ := strconv.Atoi(s)
|
|
return scheduleDue(n)
|
|
}
|
|
return scheduleCron(s)
|
|
}
|
|
|
|
// * * * * *
|
|
type scheduleCron string
|
|
|
|
func (c scheduleCron) next(t time.Time) (time.Time, error) {
|
|
schedule, err := cron.ParseStandard(string(c))
|
|
if err != nil {
|
|
return time.Time{}, err
|
|
}
|
|
return schedule.Next(t), nil
|
|
}
|
|
|
|
// * * * * *
|
|
type scheduleNever struct{}
|
|
|
|
var never = time.Date(
|
|
math.MaxInt32,
|
|
1,
|
|
1,
|
|
1,
|
|
1,
|
|
1,
|
|
1,
|
|
time.UTC,
|
|
)
|
|
|
|
func (cron scheduleNever) next(time.Time) (time.Time, error) {
|
|
return never, nil
|
|
}
|
|
|
|
// 4h5m
|
|
type scheduleDuration string
|
|
|
|
var scheduleDurationPattern = regexp.MustCompile(`^([0-9]+[a-z])+$`)
|
|
|
|
func (dur scheduleDuration) next(t time.Time) (time.Time, error) {
|
|
d, err := time.ParseDuration(string(dur))
|
|
return t.Add(d), err
|
|
}
|
|
|
|
// 123
|
|
type scheduleDue int64
|
|
|
|
var scheduleDuePattern = regexp.MustCompile(`^[0-9]+$`)
|
|
|
|
func (due scheduleDue) next(time.Time) (time.Time, error) {
|
|
return TS(due).time(), nil
|
|
}
|