1use crate::error::TypeError;
2use chrono::{DateTime, Utc};
3use cron::Schedule;
4use pyo3::prelude::*;
5use serde::{Deserialize, Serialize};
6use std::fmt;
7use std::str::FromStr;
8
9#[pyclass(eq)]
10#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
11pub enum CommonCrons {
12 Every1Minute,
13 Every5Minutes,
14 Every15Minutes,
15 Every30Minutes,
16 EveryHour,
17 Every6Hours,
18 Every12Hours,
19 EveryDay,
20 EveryWeek,
21}
22
23#[pymethods]
24impl CommonCrons {
25 #[getter]
26 pub fn cron(&self) -> String {
27 match self {
28 CommonCrons::Every1Minute => "0 * * * * * *".to_string(),
29 CommonCrons::Every5Minutes => {
30 "0 0,5,10,15,20,25,30,35,40,45,50,55 * * * * *".to_string()
31 }
32 CommonCrons::Every15Minutes => "0 0,15,30,45 * * * * *".to_string(),
33 CommonCrons::Every30Minutes => "0 0,30 * * * * *".to_string(),
34 CommonCrons::EveryHour => "0 0 * * * *".to_string(),
35 CommonCrons::Every6Hours => "0 0 */6 * * *".to_string(),
36 CommonCrons::Every12Hours => "0 0 */12 * * *".to_string(),
37 CommonCrons::EveryDay => "0 0 0 * * *".to_string(),
38 CommonCrons::EveryWeek => "0 0 0 * * SUN".to_string(),
39 }
40 }
41
42 pub fn get_next(&self) -> String {
43 match self {
44 CommonCrons::Every1Minute => {
45 let schedule = Schedule::from_str("0 * * * * * *").unwrap();
46 schedule.upcoming(Utc).next().unwrap().to_string()
47 }
48 CommonCrons::Every5Minutes => {
49 let schedule =
50 Schedule::from_str("0 0,5,10,15,20,25,30,35,40,45,50,55 * * * * *").unwrap();
51 schedule.upcoming(Utc).next().unwrap().to_string()
52 }
53 CommonCrons::Every15Minutes => {
54 let schedule = Schedule::from_str("0 0,15,30,45 * * * * *").unwrap();
55 schedule.upcoming(Utc).next().unwrap().to_string()
56 }
57 CommonCrons::Every30Minutes => {
58 let schedule = Schedule::from_str("0 0,30 * * * * *").unwrap();
59 schedule.upcoming(Utc).next().unwrap().to_string()
60 }
61 CommonCrons::EveryHour => {
62 let schedule = Schedule::from_str("0 0 * * * *").unwrap();
63 schedule.upcoming(Utc).next().unwrap().to_string()
64 }
65 CommonCrons::Every6Hours => {
66 let schedule = Schedule::from_str("0 0 */6 * * *").unwrap();
67 schedule.upcoming(Utc).next().unwrap().to_string()
68 }
69 CommonCrons::Every12Hours => {
70 let schedule = Schedule::from_str("0 0 */12 * * *").unwrap();
71 schedule.upcoming(Utc).next().unwrap().to_string()
72 }
73 CommonCrons::EveryDay => {
74 let schedule = Schedule::from_str("0 0 0 * * *").unwrap();
75 schedule.upcoming(Utc).next().unwrap().to_string()
76 }
77 CommonCrons::EveryWeek => {
78 let schedule = Schedule::from_str("0 0 0 * * SUN").unwrap();
79 schedule.upcoming(Utc).next().unwrap().to_string()
80 }
81 }
82 }
83}
84
85#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
86pub struct CustomInterval {
87 pub start: DateTime<Utc>,
88 pub end: DateTime<Utc>,
89}
90
91impl CustomInterval {
92 pub fn new(start: DateTime<Utc>, end: DateTime<Utc>) -> Result<Self, TypeError> {
93 if start >= end {
94 return Err(TypeError::StartTimeError);
95 }
96 Ok(CustomInterval { start, end })
97 }
98}
99
100#[pyclass(eq)]
101#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, Default)]
102pub enum TimeInterval {
103 FiveMinutes,
104 FifteenMinutes,
105 ThirtyMinutes,
106 OneHour,
107 #[default]
108 ThreeHours,
109 SixHours,
110 TwelveHours,
111 TwentyFourHours,
112 TwoDays,
113 FiveDays,
114}
115
116impl TimeInterval {
117 pub fn to_minutes(&self) -> i32 {
118 match self {
119 TimeInterval::FiveMinutes => 5,
120 TimeInterval::FifteenMinutes => 15,
121 TimeInterval::ThirtyMinutes => 30,
122 TimeInterval::OneHour => 60,
123 TimeInterval::ThreeHours => 180,
124 TimeInterval::SixHours => 360,
125 TimeInterval::TwelveHours => 720,
126 TimeInterval::TwentyFourHours => 1440,
127 TimeInterval::TwoDays => 2880,
128 TimeInterval::FiveDays => 7200,
129 }
130 }
131
132 pub fn from_string(time_interval: &str) -> TimeInterval {
133 match time_interval {
134 "5minute" => TimeInterval::FiveMinutes,
135 "15minute" => TimeInterval::FifteenMinutes,
136 "30minute" => TimeInterval::ThirtyMinutes,
137 "1hour" => TimeInterval::OneHour,
138 "3hour" => TimeInterval::ThreeHours,
139 "6hour" => TimeInterval::SixHours,
140 "12hour" => TimeInterval::TwelveHours,
141 "24hour" => TimeInterval::TwentyFourHours,
142 "2day" => TimeInterval::TwoDays,
143 "5day" => TimeInterval::FiveDays,
144 _ => TimeInterval::SixHours,
145 }
146 }
147}
148
149impl fmt::Display for TimeInterval {
150 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
151 match self {
152 TimeInterval::FiveMinutes => write!(f, "5minute"),
153 TimeInterval::FifteenMinutes => write!(f, "15minute"),
154 TimeInterval::ThirtyMinutes => write!(f, "30minute"),
155 TimeInterval::OneHour => write!(f, "1hour"),
156 TimeInterval::ThreeHours => write!(f, "3hour"),
157 TimeInterval::SixHours => write!(f, "6hour"),
158 TimeInterval::TwelveHours => write!(f, "12hour"),
159 TimeInterval::TwentyFourHours => write!(f, "24hour"),
160 TimeInterval::TwoDays => write!(f, "2day"),
161 TimeInterval::FiveDays => write!(f, "5day"),
162 }
163 }
164}
165
166#[cfg(test)]
169mod tests {
170 use super::*;
171
172 #[test]
173 fn test_every_30_minutes_cron() {
174 let cron = CommonCrons::Every30Minutes;
175
176 assert_eq!(cron.cron(), "0 0,30 * * * * *");
178
179 let _next = cron.get_next();
181 }
182
183 #[test]
184 fn test_every_hour_cron() {
185 let cron = CommonCrons::EveryHour;
186 assert_eq!(cron.cron(), "0 0 * * * *");
188 let _next = cron.get_next();
189 }
190
191 #[test]
192 fn test_every_6_hours_cron() {
193 let cron = CommonCrons::Every6Hours;
194 assert_eq!(cron.cron(), "0 0 */6 * * *");
196 let _next = cron.get_next();
197 }
198
199 #[test]
200 fn test_every_12_hours_cron() {
201 let cron = CommonCrons::Every12Hours;
202 assert_eq!(cron.cron(), "0 0 */12 * * *");
204 let _next = cron.get_next();
205 }
206
207 #[test]
208 fn test_every_day_cron() {
209 let cron = CommonCrons::EveryDay;
210 assert_eq!(cron.cron(), "0 0 0 * * *");
212 let _next = cron.get_next();
213 }
214
215 #[test]
216 fn test_every_week_cron() {
217 let cron = CommonCrons::EveryWeek;
218 assert_eq!(cron.cron(), "0 0 0 * * SUN");
220 let _next = cron.get_next();
221 }
222
223 #[test]
224 fn test_cron_schedule_cron() {
225 let cron = CommonCrons::Every1Minute;
226 let schedule = Schedule::from_str(&cron.cron()).unwrap();
227 let next = schedule.upcoming(Utc).next().unwrap();
228 assert_eq!(next.to_string(), cron.get_next());
229
230 let cron = CommonCrons::Every5Minutes;
231 let schedule = Schedule::from_str(&cron.cron()).unwrap();
232 let next = schedule.upcoming(Utc).next().unwrap();
233 assert_eq!(next.to_string(), cron.get_next());
234
235 let cron = CommonCrons::Every15Minutes;
236 let schedule = Schedule::from_str(&cron.cron()).unwrap();
237 let next = schedule.upcoming(Utc).next().unwrap();
238 assert_eq!(next.to_string(), cron.get_next());
239
240 let cron = CommonCrons::Every30Minutes;
241 let schedule = Schedule::from_str(&cron.cron()).unwrap();
242 let next = schedule.upcoming(Utc).next().unwrap();
243 assert_eq!(next.to_string(), cron.get_next());
244
245 let cron = CommonCrons::EveryHour;
246 let schedule = Schedule::from_str(&cron.cron()).unwrap();
247 let next = schedule.upcoming(Utc).next().unwrap();
248 assert_eq!(next.to_string(), cron.get_next());
249
250 let cron = CommonCrons::Every6Hours;
251 let schedule = Schedule::from_str(&cron.cron()).unwrap();
252 let next = schedule.upcoming(Utc).next().unwrap();
253 assert_eq!(next.to_string(), cron.get_next());
254
255 let cron = CommonCrons::Every12Hours;
256 let schedule = Schedule::from_str(&cron.cron()).unwrap();
257 let next = schedule.upcoming(Utc).next().unwrap();
258 assert_eq!(next.to_string(), cron.get_next());
259
260 let cron = CommonCrons::EveryDay;
261 let schedule = Schedule::from_str(&cron.cron()).unwrap();
262 let next = schedule.upcoming(Utc).next().unwrap();
263 assert_eq!(next.to_string(), cron.get_next());
264
265 let cron = CommonCrons::EveryWeek;
266 let schedule = Schedule::from_str(&cron.cron()).unwrap();
267 let next = schedule.upcoming(Utc).next().unwrap();
268 assert_eq!(next.to_string(), cron.get_next());
269 }
270}