@@ -8,14 +8,25 @@ use std::fs;
88use uuid:: Uuid ;
99
1010use crate :: config;
11+ use crate :: datetime:: add_months;
12+
13+ #[ derive( Serialize , Deserialize , Clone , Debug ) ]
14+ pub enum RecurrenceInterval {
15+ Minutes ( i64 ) ,
16+ Hourly ( i64 ) ,
17+ Daily ( i64 ) ,
18+ Weekly ( i64 ) ,
19+ Monthly ( i64 ) ,
20+ Yearly ( i64 ) ,
21+ }
1122
1223#[ derive( Serialize , Deserialize , Clone , Debug ) ]
1324#[ serde( untagged) ]
1425pub enum Recurrence {
1526 None ,
1627 Recurring {
1728 last_recurrence : Option < DateTime < Utc > > ,
18- minutes : i64 ,
29+ interval : RecurrenceInterval ,
1930 exceptions : Option < Vec < DateTime < Utc > > > ,
2031 } ,
2132}
@@ -149,11 +160,11 @@ impl TaskReminder {
149160 for i in 0 ..instances_required {
150161 let recurrence_info = if let Some ( Recurrence :: Recurring {
151162 last_recurrence,
152- minutes ,
163+ interval ,
153164 exceptions,
154165 } ) = & d. recurrence
155166 {
156- Some ( ( last_recurrence, minutes , exceptions) )
167+ Some ( ( last_recurrence, interval , exceptions) )
157168 } else {
158169 None
159170 } ;
@@ -164,12 +175,51 @@ impl TaskReminder {
164175 }
165176
166177 let timestamp = match recurrence_info {
167- Some ( ( last_recurrence, minutes, _exceptions) ) => match * last_recurrence {
168- Some ( last) => last + Duration :: minutes ( ( i + 1 ) * minutes) ,
169-
170- None => d. start + Duration :: minutes ( i * minutes) ,
178+ Some ( ( last_recurrence, interval, _) ) => match interval {
179+ RecurrenceInterval :: Minutes ( number) => {
180+ if let Some ( last) = last_recurrence {
181+ * last + Duration :: minutes ( ( i + 1 ) * number)
182+ } else {
183+ d. start + Duration :: minutes ( i * number)
184+ }
185+ }
186+ RecurrenceInterval :: Hourly ( number) => {
187+ if let Some ( last) = last_recurrence {
188+ * last + Duration :: hours ( ( i + 1 ) * number)
189+ } else {
190+ d. start + Duration :: hours ( i * number)
191+ }
192+ }
193+ RecurrenceInterval :: Daily ( number) => {
194+ if let Some ( last) = last_recurrence {
195+ * last + Duration :: days ( ( i + 1 ) * number)
196+ } else {
197+ d. start + Duration :: days ( i * number)
198+ }
199+ }
200+ RecurrenceInterval :: Weekly ( number) => {
201+ if let Some ( last) = last_recurrence {
202+ * last + Duration :: weeks ( ( i + 1 ) * number)
203+ } else {
204+ d. start + Duration :: weeks ( i * number)
205+ }
206+ }
207+ RecurrenceInterval :: Monthly ( number) => {
208+ let mut t = last_recurrence. unwrap_or ( d. start ) ;
209+ for _ in 0 ..=( i as u32 ) {
210+ t = add_months ( t, * number as u32 ) ;
211+ }
212+ t
213+ }
214+ RecurrenceInterval :: Yearly ( number) => {
215+ let mut t = last_recurrence. unwrap_or ( d. start ) ;
216+ for _ in 0 ..=( i as u32 ) {
217+ t = add_months ( t, 12 * ( * number as u32 ) ) ;
218+ }
219+ t
220+ }
171221 } ,
172- _ => d. start ,
222+ None => d. start ,
173223 } ;
174224
175225 let exceptions = if let Some ( recurrence) = recurrence_info {
@@ -251,7 +301,7 @@ impl TaskReminder {
251301 if let Some ( definition) = self . get_task_definition_mut ( task. definition_id ) {
252302 if let Some ( Recurrence :: Recurring {
253303 last_recurrence,
254- minutes : _,
304+ interval : _,
255305 exceptions : _,
256306 } ) = & mut definition. recurrence
257307 {
@@ -316,7 +366,7 @@ mod tests {
316366 start : Utc . with_ymd_and_hms ( 2025 , 1 , 1 , 12 , 0 , 0 ) . unwrap ( ) ,
317367 recurrence : Some ( Recurrence :: Recurring {
318368 last_recurrence : None ,
319- minutes : 60 ,
369+ interval : RecurrenceInterval :: Minutes ( 60 ) ,
320370 exceptions : None ,
321371 } ) ,
322372 }
@@ -436,7 +486,7 @@ mod tests {
436486 start,
437487 recurrence: Some ( Recurrence :: Recurring {
438488 last_recurrence: None ,
439- minutes : 60 ,
489+ interval : RecurrenceInterval :: Minutes ( 60 ) ,
440490 exceptions: Some ( vec![ exception_time] ) ,
441491 } ) ,
442492 } ] ,
@@ -462,7 +512,7 @@ mod tests {
462512 start : Utc . with_ymd_and_hms ( 2025 , 1 , 1 , 8 , 0 , 0 ) . unwrap ( ) ,
463513 recurrence : Some ( Recurrence :: Recurring {
464514 last_recurrence : None ,
465- minutes : 5 , // small interval to fill multiple pages quickly
515+ interval : RecurrenceInterval :: Minutes ( 60 ) ,
466516 exceptions : None ,
467517 } ) ,
468518 } ;
0 commit comments