89 lines
2.0 KiB
Go
89 lines
2.0 KiB
Go
package publishschedule
|
|
|
|
import (
|
|
"sort"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
type Slot struct {
|
|
Weekday int
|
|
Time string
|
|
}
|
|
|
|
func BuildSchedule(startAt int64, timezone string, slots []Slot, count int) []int64 {
|
|
if count <= 0 {
|
|
return nil
|
|
}
|
|
loc := time.UTC
|
|
if strings.TrimSpace(timezone) != "" {
|
|
if loaded, err := time.LoadLocation(strings.TrimSpace(timezone)); err == nil {
|
|
loc = loaded
|
|
}
|
|
}
|
|
start := time.Now().In(loc)
|
|
if startAt > 0 {
|
|
start = time.Unix(0, startAt).In(loc)
|
|
}
|
|
normalized := normalizeSlots(slots)
|
|
if len(normalized) == 0 {
|
|
out := make([]int64, 0, count)
|
|
for i := 0; i < count; i++ {
|
|
out = append(out, start.Add(time.Duration(i)*2*time.Hour).UTC().UnixNano())
|
|
}
|
|
return out
|
|
}
|
|
out := make([]int64, 0, count)
|
|
day := time.Date(start.Year(), start.Month(), start.Day(), 0, 0, 0, 0, loc)
|
|
for len(out) < count {
|
|
for _, slot := range normalized {
|
|
if int(day.Weekday()) != slot.Weekday {
|
|
continue
|
|
}
|
|
hour, minute, ok := parseHHMM(slot.Time)
|
|
if !ok {
|
|
continue
|
|
}
|
|
candidate := time.Date(day.Year(), day.Month(), day.Day(), hour, minute, 0, 0, loc)
|
|
if candidate.Before(start) {
|
|
continue
|
|
}
|
|
out = append(out, candidate.UTC().UnixNano())
|
|
if len(out) >= count {
|
|
break
|
|
}
|
|
}
|
|
day = day.AddDate(0, 0, 1)
|
|
}
|
|
return out
|
|
}
|
|
|
|
func normalizeSlots(slots []Slot) []Slot {
|
|
out := make([]Slot, 0, len(slots))
|
|
for _, slot := range slots {
|
|
if strings.TrimSpace(slot.Time) == "" {
|
|
continue
|
|
}
|
|
weekday := slot.Weekday
|
|
if weekday < 0 || weekday > 6 {
|
|
weekday = ((weekday % 7) + 7) % 7
|
|
}
|
|
out = append(out, Slot{Weekday: weekday, Time: strings.TrimSpace(slot.Time)})
|
|
}
|
|
sort.Slice(out, func(i, j int) bool {
|
|
if out[i].Weekday == out[j].Weekday {
|
|
return out[i].Time < out[j].Time
|
|
}
|
|
return out[i].Weekday < out[j].Weekday
|
|
})
|
|
return out
|
|
}
|
|
|
|
func parseHHMM(value string) (int, int, bool) {
|
|
parsed, err := time.Parse("15:04", strings.TrimSpace(value))
|
|
if err != nil {
|
|
return 0, 0, false
|
|
}
|
|
return parsed.Hour(), parsed.Minute(), true
|
|
}
|