-
Notifications
You must be signed in to change notification settings - Fork 0
/
schedule.go
123 lines (109 loc) · 2.83 KB
/
schedule.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
118
119
120
121
122
123
package timechart
import (
"fmt"
"time"
)
type Schedule struct {
Start time.Time
End time.Time
}
func NewSchedule(start, end time.Time) Schedule {
return Schedule{
Start: start,
End: end,
}
}
func (s Schedule) String() string {
return fmt.Sprintf("%s-%s", s.Start.Format("15:04"), s.End.Format("15:04"))
}
func (s Schedule) IsOverlapped(other Schedule) bool {
switch {
case s.Contains(other.Start) && timeLTE(s.End, other.End):
return true
case s.Contains(other.End) && timeGTE(s.Start, other.Start):
return true
case other.Contains(s.Start) && other.Contains(s.End):
return true
case s.Contains(other.Start) && s.Contains(other.End):
return true
default:
return false
}
}
func (s Schedule) Overlap(other Schedule) Schedule {
// ├──────┤ s
// + ├──────┤ other
// = ├───━━━━───┤
if s.Contains(other.Start) && timeLTE(s.End, other.End) {
s.End = other.End
return s
}
// ├──────┤ s
// + ├──────┤ other
// = ├───━━━━───┤
if s.Contains(other.End) && timeGTE(s.Start, other.Start) {
s.Start = other.Start
return s
}
// ├───┤ s
// + ├───────┤ other
// = ├─━━━━━─┤
if other.Contains(s.Start) && other.Contains(s.End) {
return other
}
// ├───────┤ s
// + ├───┤ other
// = ├─━━━━━─┤
if s.Contains(other.Start) && s.Contains(other.End) {
return s
}
return s
}
// Contains returns true if t is in s.
// e.g. if ├──────────┤ s
// t1 (true) t2 (false)
func (s Schedule) Contains(t time.Time) bool {
return timeGTE(t, s.Start) && timeLTE(t, s.End)
}
// OverlapSchedules returns new overlapped schedules from given ss.
// e.g. if [14:00-16:00, 13:00-15:00] are given, returns [13:00-16:00]
func OverlapSchedules(ss []Schedule) []Schedule {
if len(ss) == 0 {
return nil
}
exists := ss[:1]
not := make([]Schedule, 0, len(ss))
for _, schedule := range ss[1:] {
found := false
for i, exist := range exists {
if exist.IsOverlapped(schedule) {
exists[i] = exist.Overlap(schedule)
found = true
break
}
}
if !found {
not = append(not, schedule)
}
}
return append(exists, not...)
}
func NewTime(h, m, s int) time.Time {
return time.Date(1, 1, 1, h, m, s, 0, time.UTC)
}
// timeGT returns t1 is greater than t2.
func timeGT(t1, t2 time.Time) bool {
return t1.After(t2)
}
// timeGTE returns t1 is greater than or equal to t2.
func timeGTE(t1, t2 time.Time) bool {
return timeGT(t1, t2) || t1.Equal(t2)
}
// timeLT returns t1 is less than t2.
func timeLT(t1, t2 time.Time) bool {
return t1.Before(t2)
}
// timeLTE returns t1 is less than or equal to t2.
func timeLTE(t1, t2 time.Time) bool {
return timeLT(t1, t2) || t1.Equal(t2)
}