-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrepeat.go
More file actions
134 lines (114 loc) · 3.48 KB
/
repeat.go
File metadata and controls
134 lines (114 loc) · 3.48 KB
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
124
125
126
127
128
129
130
131
132
133
134
package cali
import (
"time"
)
func GenerateRepeatEvents(e Event) ([]*Event, error) {
if !e.IsRepeating {
return nil, ErrorNotRepeatingEvent
}
startDay, err := time.Parse(time.DateOnly, e.StartDay)
if err != nil {
return nil, ErrorInvalidStartDay
}
endDay, err := time.Parse(time.DateOnly, e.EndDay)
if err != nil {
return nil, ErrorInvalidEndDay
}
nextStart := startDay
nextEnd := endDay
year, month, day := 0, 0, 0
increment := func() {
nextStart = nextStart.AddDate(year, month, day)
nextEnd = nextEnd.AddDate(year, month, day)
}
if err := Validate(e); err != nil {
return nil, err
}
r := e.Repeat
var events []*Event
switch e.Repeat.RepeatType {
case RepeatTypeDaily, RepeatTypeMonthly, RepeatTypeYearly:
events = append(events, &e)
// daily, monthly, and yearly repeats are all the same
// kind of repeating
switch e.Repeat.RepeatType {
case RepeatTypeDaily:
day++
case RepeatTypeMonthly:
month++
case RepeatTypeYearly:
year++
}
if r.RepeatOccurrences >= 2 {
// loop until there are a specific number of events
for len(events) < int(r.RepeatOccurrences) {
nextEvent := e
increment()
nextEvent.StartDay = nextStart.Format(time.DateOnly)
nextEvent.EndDay = nextEnd.Format(time.DateOnly)
events = append(events, &nextEvent)
}
} else if r.RepeatStopDate != nil {
// loop until the next start date is after the stop date
for !nextStart.After(*r.RepeatStopDate) {
// if there are more event repeats than allowed, throw error
if len(events) > int(MaxRepeatOccurrence) {
return nil, ErrorTooManyRepeatOccurrences
}
nextEvent := e
increment()
nextEvent.StartDay = nextStart.Format(time.DateOnly)
nextEvent.EndDay = nextEnd.Format(time.DateOnly)
events = append(events, &nextEvent)
}
}
case RepeatTypeWeekly:
// set the increment to move up one day at a time
day++
// weekly repeating happens based on the day of the week which
// means the initial event could actually be not in the repeating
// events. Ex: initial event is on a Wednesday, but the DayOfWeek
// says Tuesday and Thursday.
if r.RepeatOccurrences >= 2 {
// loop until there are a specific number of events
for len(events) < int(r.RepeatOccurrences) {
day := dayOfWeekFromWeekday(nextStart.Weekday())
if !r.DayOfWeek.HasFlag(day) {
increment()
continue
}
nextEvent := e
nextEvent.StartDay = nextStart.Format(time.DateOnly)
nextEvent.EndDay = nextEnd.Format(time.DateOnly)
events = append(events, &nextEvent)
// go to the next day (do this at the end of the for loop
// since we need to check the original event)
increment()
}
} else if r.RepeatStopDate != nil {
// loop until the next start date is after the stop date
for !nextStart.After(*r.RepeatStopDate) {
// if there are more event repeats than allowed, throw error
if len(events) > int(MaxRepeatOccurrence) {
return nil, ErrorTooManyRepeatOccurrences
}
day := dayOfWeekFromWeekday(nextStart.Weekday())
if !r.DayOfWeek.HasFlag(day) {
increment()
continue
}
nextEvent := e
nextEvent.StartDay = nextStart.Format(time.DateOnly)
nextEvent.EndDay = nextEnd.Format(time.DateOnly)
events = append(events, &nextEvent)
// go to the next day (do this at the end of the for loop
// since we need to check the original event)
increment()
}
}
}
if events == nil || len(events) == 0 {
return nil, ErrorEmptyRepeatingEvents
}
return events, nil
}