-
Notifications
You must be signed in to change notification settings - Fork 37
/
time.go
117 lines (99 loc) · 2.7 KB
/
time.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
package main
import (
"errors"
"fmt"
"strings"
"time"
)
var dayAbbreviations = map[rune]time.Weekday{
'S': time.Sunday,
'M': time.Monday,
'T': time.Tuesday,
'W': time.Wednesday,
'H': time.Thursday,
'F': time.Friday,
'A': time.Saturday,
}
// ParseWeekdayList takes a string of one-letter weekday abbreviations (like
// "MWF" and returns an array of booleans, one for each day of the week, which
// are true if that day was included. The weekday abbreviations are SMTWHFA.
func ParseWeekdayList(list string) (days [7]bool, err error) {
list = strings.ToUpper(list)
for _, c := range list {
d, ok := dayAbbreviations[c]
if !ok {
return [7]bool{}, fmt.Errorf("invalid weekday abbreviation (%c) in %q", c, list)
}
if days[d] {
return [7]bool{}, fmt.Errorf("repeated day (%v) in %q", d, list)
}
days[d] = true
}
return days, nil
}
// A TimeRange is a range of times within a day. Start and End are expressed in
// minutes since midnight.
type TimeRange struct {
Start, End int
}
// ParseTimeRange parses a time range in the format hh:mm-hh:mm (24-hour).
func ParseTimeRange(s string) (r TimeRange, err error) {
var startH, startM, endH, endM int
n, err := fmt.Sscanf(s, "%d:%d-%d:%d", &startH, &startM, &endH, &endM)
if err != nil || n != 4 {
return TimeRange{}, fmt.Errorf("invalid time range string %q", s)
}
r.Start = startH*60 + startM
r.End = endH*60 + endM
if r.Start >= r.End {
return TimeRange{}, fmt.Errorf("invalid time range %q (Did you forget to use 24-hour clock?)", s)
}
return r, nil
}
// A WeeklySchedule is a set of time periods, occurring on certain days of the
// week and repeating each week.
type WeeklySchedule struct {
Days [7]bool
Times []TimeRange
}
// ParseWeeklySchedule reads an optional weekday list, and any number of
// TimeRanges, into a WeeklySchedule.
func ParseWeeklySchedule(src []string) (schedule WeeklySchedule, err error) {
if len(src) == 0 {
return WeeklySchedule{}, errors.New("no data")
}
if days := src[0]; days != "" && 'A' <= days[0] && days[0] <= 'Z' {
src = src[1:]
schedule.Days, err = ParseWeekdayList(days)
if err != nil {
return WeeklySchedule{}, err
}
} else {
for i := range schedule.Days {
schedule.Days[i] = true
}
}
for _, times := range src {
tr, err := ParseTimeRange(times)
if err != nil {
return WeeklySchedule{}, err
}
schedule.Times = append(schedule.Times, tr)
}
return schedule, nil
}
func (w WeeklySchedule) Contains(day time.Weekday, hour int, min int) bool {
if !w.Days[day] {
return false
}
if len(w.Times) == 0 {
return true
}
minuteOfDay := hour*60 + min
for _, tr := range w.Times {
if tr.Start <= minuteOfDay && minuteOfDay <= tr.End {
return true
}
}
return false
}