use crate::error::TypeError;
use chrono::{DateTime, Utc};
use cron::Schedule;
use pyo3::prelude::*;
use serde::{Deserialize, Serialize};
use std::fmt;
use std::str::FromStr;
#[pyclass(eq)]
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
pub enum CommonCrons {
Every1Minute,
Every5Minutes,
Every15Minutes,
Every30Minutes,
EveryHour,
Every6Hours,
Every12Hours,
EveryDay,
EveryWeek,
}
#[pymethods]
impl CommonCrons {
#[getter]
pub fn cron(&self) -> String {
match self {
CommonCrons::Every1Minute => "0 * * * * * *".to_string(),
CommonCrons::Every5Minutes => {
"0 0,5,10,15,20,25,30,35,40,45,50,55 * * * * *".to_string()
}
CommonCrons::Every15Minutes => "0 0,15,30,45 * * * * *".to_string(),
CommonCrons::Every30Minutes => "0 0,30 * * * * *".to_string(),
CommonCrons::EveryHour => "0 0 * * * *".to_string(),
CommonCrons::Every6Hours => "0 0 */6 * * *".to_string(),
CommonCrons::Every12Hours => "0 0 */12 * * *".to_string(),
CommonCrons::EveryDay => "0 0 0 * * *".to_string(),
CommonCrons::EveryWeek => "0 0 0 * * SUN".to_string(),
}
}
pub fn get_next(&self) -> String {
match self {
CommonCrons::Every1Minute => {
let schedule = Schedule::from_str("0 * * * * * *").unwrap();
schedule.upcoming(Utc).next().unwrap().to_string()
}
CommonCrons::Every5Minutes => {
let schedule =
Schedule::from_str("0 0,5,10,15,20,25,30,35,40,45,50,55 * * * * *").unwrap();
schedule.upcoming(Utc).next().unwrap().to_string()
}
CommonCrons::Every15Minutes => {
let schedule = Schedule::from_str("0 0,15,30,45 * * * * *").unwrap();
schedule.upcoming(Utc).next().unwrap().to_string()
}
CommonCrons::Every30Minutes => {
let schedule = Schedule::from_str("0 0,30 * * * * *").unwrap();
schedule.upcoming(Utc).next().unwrap().to_string()
}
CommonCrons::EveryHour => {
let schedule = Schedule::from_str("0 0 * * * *").unwrap();
schedule.upcoming(Utc).next().unwrap().to_string()
}
CommonCrons::Every6Hours => {
let schedule = Schedule::from_str("0 0 */6 * * *").unwrap();
schedule.upcoming(Utc).next().unwrap().to_string()
}
CommonCrons::Every12Hours => {
let schedule = Schedule::from_str("0 0 */12 * * *").unwrap();
schedule.upcoming(Utc).next().unwrap().to_string()
}
CommonCrons::EveryDay => {
let schedule = Schedule::from_str("0 0 0 * * *").unwrap();
schedule.upcoming(Utc).next().unwrap().to_string()
}
CommonCrons::EveryWeek => {
let schedule = Schedule::from_str("0 0 0 * * SUN").unwrap();
schedule.upcoming(Utc).next().unwrap().to_string()
}
}
}
}
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
pub struct CustomInterval {
pub begin: DateTime<Utc>,
pub end: DateTime<Utc>,
}
impl CustomInterval {
pub fn new(begin: DateTime<Utc>, end: DateTime<Utc>) -> Result<Self, TypeError> {
if begin >= end {
return Err(TypeError::StartTimeError);
}
Ok(CustomInterval { begin, end })
}
}
#[pyclass(eq)]
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, Default)]
pub enum TimeInterval {
FifteenMinutes,
ThirtyMinutes,
OneHour,
#[default]
FourHours,
SixHours,
TwelveHours,
TwentyFourHours,
SevenDays,
Custom,
}
impl TimeInterval {
pub fn to_minutes(&self) -> i32 {
match self {
TimeInterval::FifteenMinutes => 15,
TimeInterval::ThirtyMinutes => 30,
TimeInterval::OneHour => 60,
TimeInterval::FourHours => 240,
TimeInterval::SixHours => 360,
TimeInterval::TwelveHours => 720,
TimeInterval::TwentyFourHours => 1440,
TimeInterval::SevenDays => 10080,
TimeInterval::Custom => 0,
}
}
pub fn to_begin_end_times(&self) -> Result<(DateTime<Utc>, DateTime<Utc>), TypeError> {
let end = Utc::now();
let start = match self {
TimeInterval::FifteenMinutes => end - chrono::Duration::minutes(15),
TimeInterval::ThirtyMinutes => end - chrono::Duration::minutes(30),
TimeInterval::OneHour => end - chrono::Duration::hours(1),
TimeInterval::FourHours => end - chrono::Duration::hours(4),
TimeInterval::SixHours => end - chrono::Duration::hours(6),
TimeInterval::TwelveHours => end - chrono::Duration::hours(12),
TimeInterval::TwentyFourHours => end - chrono::Duration::hours(24),
TimeInterval::SevenDays => end - chrono::Duration::days(7),
_ => {
return Err(TypeError::InvalidTimeIntervalError);
}
};
Ok((start, end))
}
pub fn from_string(time_interval: &str) -> TimeInterval {
match time_interval {
"15minute" => TimeInterval::FifteenMinutes,
"30minute" => TimeInterval::ThirtyMinutes,
"1hour" => TimeInterval::OneHour,
"4hour" => TimeInterval::FourHours,
"6hour" => TimeInterval::SixHours,
"12hour" => TimeInterval::TwelveHours,
"24hour" => TimeInterval::TwentyFourHours,
"7day" => TimeInterval::SevenDays,
"custom" => TimeInterval::Custom,
_ => TimeInterval::SixHours,
}
}
}
impl fmt::Display for TimeInterval {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
TimeInterval::FifteenMinutes => write!(f, "15minute"),
TimeInterval::ThirtyMinutes => write!(f, "30minute"),
TimeInterval::OneHour => write!(f, "1hour"),
TimeInterval::FourHours => write!(f, "4hour"),
TimeInterval::SixHours => write!(f, "6hour"),
TimeInterval::TwelveHours => write!(f, "12hour"),
TimeInterval::TwentyFourHours => write!(f, "24hour"),
TimeInterval::SevenDays => write!(f, "7day"),
TimeInterval::Custom => write!(f, "custom"),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_every_30_minutes_cron() {
let cron = CommonCrons::Every30Minutes;
assert_eq!(cron.cron(), "0 0,30 * * * * *");
let _next = cron.get_next();
}
#[test]
fn test_every_hour_cron() {
let cron = CommonCrons::EveryHour;
assert_eq!(cron.cron(), "0 0 * * * *");
let _next = cron.get_next();
}
#[test]
fn test_every_6_hours_cron() {
let cron = CommonCrons::Every6Hours;
assert_eq!(cron.cron(), "0 0 */6 * * *");
let _next = cron.get_next();
}
#[test]
fn test_every_12_hours_cron() {
let cron = CommonCrons::Every12Hours;
assert_eq!(cron.cron(), "0 0 */12 * * *");
let _next = cron.get_next();
}
#[test]
fn test_every_day_cron() {
let cron = CommonCrons::EveryDay;
assert_eq!(cron.cron(), "0 0 0 * * *");
let _next = cron.get_next();
}
#[test]
fn test_every_week_cron() {
let cron = CommonCrons::EveryWeek;
assert_eq!(cron.cron(), "0 0 0 * * SUN");
let _next = cron.get_next();
}
#[test]
fn test_cron_schedule_cron() {
let cron = CommonCrons::Every1Minute;
let schedule = Schedule::from_str(&cron.cron()).unwrap();
let next = schedule.upcoming(Utc).next().unwrap();
assert_eq!(next.to_string(), cron.get_next());
let cron = CommonCrons::Every5Minutes;
let schedule = Schedule::from_str(&cron.cron()).unwrap();
let next = schedule.upcoming(Utc).next().unwrap();
assert_eq!(next.to_string(), cron.get_next());
let cron = CommonCrons::Every15Minutes;
let schedule = Schedule::from_str(&cron.cron()).unwrap();
let next = schedule.upcoming(Utc).next().unwrap();
assert_eq!(next.to_string(), cron.get_next());
let cron = CommonCrons::Every30Minutes;
let schedule = Schedule::from_str(&cron.cron()).unwrap();
let next = schedule.upcoming(Utc).next().unwrap();
assert_eq!(next.to_string(), cron.get_next());
let cron = CommonCrons::EveryHour;
let schedule = Schedule::from_str(&cron.cron()).unwrap();
let next = schedule.upcoming(Utc).next().unwrap();
assert_eq!(next.to_string(), cron.get_next());
let cron = CommonCrons::Every6Hours;
let schedule = Schedule::from_str(&cron.cron()).unwrap();
let next = schedule.upcoming(Utc).next().unwrap();
assert_eq!(next.to_string(), cron.get_next());
let cron = CommonCrons::Every12Hours;
let schedule = Schedule::from_str(&cron.cron()).unwrap();
let next = schedule.upcoming(Utc).next().unwrap();
assert_eq!(next.to_string(), cron.get_next());
let cron = CommonCrons::EveryDay;
let schedule = Schedule::from_str(&cron.cron()).unwrap();
let next = schedule.upcoming(Utc).next().unwrap();
assert_eq!(next.to_string(), cron.get_next());
let cron = CommonCrons::EveryWeek;
let schedule = Schedule::from_str(&cron.cron()).unwrap();
let next = schedule.upcoming(Utc).next().unwrap();
assert_eq!(next.to_string(), cron.get_next());
}
}