65 lines
1.9 KiB
Go
65 lines
1.9 KiB
Go
package core
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
func GetNextUpdate(lastUpdated time.Time, spec string) (nextUpdate time.Time, err error) {
|
|
var nextUpdates []time.Time
|
|
switch {
|
|
case strings.HasPrefix(spec, "every "):
|
|
nextUpdates, err = parseEverySpec(lastUpdated, spec[len("every "):])
|
|
case strings.HasPrefix(spec, "at "):
|
|
nextUpdates, err = parseAtSpec(lastUpdated, spec[len("at "):])
|
|
default:
|
|
return time.Time{}, fmt.Errorf("unknown spec format: %v", spec)
|
|
}
|
|
if err != nil {
|
|
return time.Time{}, err
|
|
}
|
|
for _, next := range nextUpdates {
|
|
if next.After(lastUpdated) && (nextUpdate.IsZero() || next.Before(nextUpdate)) {
|
|
nextUpdate = next
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// Get the next instance of the every-spec after the base time.
|
|
// An every-spec is a Go duration string.
|
|
func parseEverySpec(base time.Time, everySpec string) (nextUpdates []time.Time, err error) {
|
|
var duration time.Duration
|
|
duration, err = time.ParseDuration(everySpec)
|
|
if err == nil {
|
|
next := base.Round(duration)
|
|
if !next.After(base) {
|
|
next = next.Add(duration)
|
|
}
|
|
nextUpdates = []time.Time{next}
|
|
}
|
|
return
|
|
}
|
|
|
|
// Get the next instances of the at-spec times after the base time.
|
|
// An at-spec is in the patterm HH:MM[,HH:MM,[...]].
|
|
func parseAtSpec(base time.Time, atSpec string) (nextUpdates []time.Time, err error) {
|
|
timeSpecs := strings.Split(atSpec, ",")
|
|
for _, timeSpec := range timeSpecs {
|
|
var hour, minute int
|
|
_, err = fmt.Sscanf(timeSpec, "%d:%d", &hour, &minute)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not parse %s: %v", timeSpec, err)
|
|
}
|
|
// The time instance on the same day as the base time
|
|
specOfDay := time.Date(base.Year(), base.Month(), base.Day(), hour, minute, 0, 0, base.Location())
|
|
// Bump it forward one day if it's before the base time
|
|
if !specOfDay.After(base) {
|
|
specOfDay = specOfDay.Add(24 * time.Hour)
|
|
}
|
|
nextUpdates = append(nextUpdates, specOfDay)
|
|
}
|
|
return
|
|
}
|