@@ -77,6 +77,7 @@ func expandByWeekdays(tt []time.Time, weekStart time.Weekday, weekdays ...Qualif
77
77
78
78
return e
79
79
}
80
+
80
81
func expandByMonthDays (tt []time.Time , monthdays ... int ) []time.Time {
81
82
if len (monthdays ) == 0 {
82
83
return tt
@@ -92,42 +93,89 @@ func expandByMonthDays(tt []time.Time, monthdays ...int) []time.Time {
92
93
return e
93
94
}
94
95
95
- func expandByYearDays (tt []time.Time , yeardays ... int ) []time.Time {
96
+ func expandByYearDays (tt []time.Time , ib InvalidBehavior , yeardays ... int ) []time.Time {
96
97
if len (yeardays ) == 0 {
97
98
return tt
98
99
}
99
100
100
101
e := make ([]time.Time , 0 , len (tt )* len (yeardays ))
101
102
for _ , t := range tt {
102
103
yearStart := time .Date (t .Year (), time .January , 1 , t .Hour (), t .Minute (), t .Second (), t .Nanosecond (), t .Location ())
104
+ startYear := yearStart .Year ()
103
105
104
106
for _ , yd := range yeardays {
105
- e = append (e , yearStart .AddDate (0 , 0 , yd ))
107
+ added := yearStart .AddDate (0 , 0 , yd - 1 ) // subtract one because we start on the 1st, so if we want yearday 1, we actually want to advance 0.
108
+ if added .Year () != startYear {
109
+ switch ib {
110
+ case OmitInvalid :
111
+ // do nothing
112
+ case NextInvalid :
113
+ e = append (e , added )
114
+ case PrevInvalid :
115
+ e = append (e , added .AddDate (0 , 0 , - 1 ))
116
+ }
117
+ } else {
118
+ e = append (e , added )
119
+ }
106
120
}
107
121
}
108
122
109
123
return e
110
124
}
111
125
112
- func expandByWeekNumbers (tt []time.Time , weekStarts time.Weekday , weekNumbers ... int ) []time.Time {
126
+ func expandByWeekNumbers (tt []time.Time , ib InvalidBehavior , weekStarts time. Weekday , byWeekdays [] time.Weekday , weekNumbers ... int ) []time.Time {
113
127
if len (weekNumbers ) == 0 {
114
128
return tt
115
129
}
116
130
117
131
e := make ([]time.Time , 0 , len (tt )* len (weekNumbers ))
118
132
for _ , t := range tt {
119
- yearStart := time .Date (t .Year (), time .January , 1 , t .Hour (), t .Minute (), t .Second (), t .Nanosecond (), t .Location ())
120
- yearStart = forwardToWeekday (yearStart , t .Weekday ())
133
+ ys := yearStart (t , weekStarts )
134
+
135
+ byWeekdays := byWeekdays
136
+ if len (byWeekdays ) == 0 {
137
+ // NOTE: the spec is not 100% clear on what to do in this case.
138
+ // rrule.js, for instance, will default to returning the full
139
+ // week. lib-recur seems to copy the weekday from the input
140
+ // time. I'm going with the latter, since it seems more consistent
141
+ // with the behavior you'd get on a BYMONTH clause.
142
+ byWeekdays = []time.Weekday {t .Weekday ()}
143
+ }
121
144
122
145
for _ , w := range weekNumbers {
123
- e = append (e , yearStart .AddDate (0 , 0 , (w - 1 )* 7 ))
146
+ ws := ys .AddDate (0 , 0 , (w - 1 )* 7 )
147
+
148
+ if weekYearStart := yearStart (ws , weekStarts ); weekYearStart .Year () != ys .Year () {
149
+ // check that the week we generated is still within the proper
150
+ // year, or if it ran over because the year did not have enough
151
+ // weeks
152
+
153
+ nextYearStart := yearStart (ys .AddDate (1 , 0 , 0 ), weekStarts )
154
+ switch ib {
155
+ case OmitInvalid :
156
+ // do nothing
157
+ case NextInvalid :
158
+ for _ , wd := range byWeekdays {
159
+ e = append (e , forwardToWeekday (nextYearStart , wd ))
160
+ }
161
+ case PrevInvalid :
162
+ for _ , wd := range byWeekdays {
163
+ e = append (e , backToWeekday (nextYearStart , wd ))
164
+ }
165
+ }
166
+ continue
167
+ }
168
+
169
+ for _ , wd := range byWeekdays {
170
+ e = append (e , forwardToWeekday (ws , wd ))
171
+ }
124
172
}
125
173
}
126
174
127
175
return e
128
176
}
129
177
130
- func expandByMonths (tt []time.Time , ib invalidBehavior , months ... time.Month ) []time.Time {
178
+ func expandByMonths (tt []time.Time , ib InvalidBehavior , months ... time.Month ) []time.Time {
131
179
if len (months ) == 0 {
132
180
return tt
133
181
}
@@ -138,13 +186,13 @@ func expandByMonths(tt []time.Time, ib invalidBehavior, months ...time.Month) []
138
186
set := time .Date (t .Year (), m , t .Day (), t .Hour (), t .Minute (), t .Second (), t .Nanosecond (), t .Location ())
139
187
if set .Month () != m {
140
188
switch ib {
141
- case prevInvalid :
189
+ case PrevInvalid :
142
190
set = time .Date (t .Year (), t .Month ()+ 1 , - 1 , t .Hour (), t .Minute (), t .Second (), t .Nanosecond (), t .Location ())
143
191
e = append (e , set )
144
- case nextInvalid :
192
+ case NextInvalid :
145
193
set = time .Date (t .Year (), t .Month ()+ 1 , 1 , t .Hour (), t .Minute (), t .Second (), t .Nanosecond (), t .Location ())
146
194
e = append (e , set )
147
- case omitInvalid :
195
+ case OmitInvalid :
148
196
// do nothing
149
197
}
150
198
} else {
@@ -160,7 +208,7 @@ func expandByMonths(tt []time.Time, ib invalidBehavior, months ...time.Month) []
160
208
// bySetPos is not nil, it is assumed tt is the full set of instances within the
161
209
// monthly iteration, and only the instances matching the posisions of bySetPos
162
210
// are returned. This is an optimization.
163
- func expandMonthByWeekdays (tt []time.Time , ib invalidBehavior , bySetPos []int , weekdays ... QualifiedWeekday ) []time.Time {
211
+ func expandMonthByWeekdays (tt []time.Time , ib InvalidBehavior , bySetPos []int , weekdays ... QualifiedWeekday ) []time.Time {
164
212
if len (weekdays ) == 0 {
165
213
return tt
166
214
}
@@ -173,7 +221,7 @@ func expandMonthByWeekdays(tt []time.Time, ib invalidBehavior, bySetPos []int, w
173
221
return e
174
222
}
175
223
176
- func expandYearByWeekdays (tt []time.Time , ib invalidBehavior , weekdays ... QualifiedWeekday ) []time.Time {
224
+ func expandYearByWeekdays (tt []time.Time , ib InvalidBehavior , weekdays ... QualifiedWeekday ) []time.Time {
177
225
if len (weekdays ) == 0 {
178
226
return tt
179
227
}
0 commit comments