use std::time::Duration;
use chrono::{Datelike, Duration as ChronoDuration, TimeZone, Utc};
use serde::{Deserialize, Serialize};
use crate::envelope::current_time;
#[derive(Debug, Clone, Deserialize, Serialize)]
pub enum Cycle {
Week,
Month,
}
impl Cycle {
pub fn start(&self) -> Duration {
let now = current_time();
match self {
Cycle::Week => beginning_of_week(now),
Cycle::Month => beginning_of_month(now),
}
}
pub fn end(&self) -> Duration {
let now = current_time();
match self {
Cycle::Week => end_of_week(now),
Cycle::Month => end_of_month(now),
}
}
}
pub fn beginning_of_week(current_time: Duration) -> Duration {
let current_date = Utc.timestamp_opt(current_time.as_secs() as i64, 0).unwrap();
let current_weekday = current_date.weekday().num_days_from_monday();
let beginning_of_week_date = current_date - ChronoDuration::days(current_weekday as i64);
let beginning_of_week_datetime = beginning_of_week_date
.date_naive()
.and_hms_opt(0, 0, 0)
.unwrap();
Duration::from_secs(beginning_of_week_datetime.timestamp() as u64)
}
pub fn beginning_of_month(current_time: Duration) -> Duration {
let current_date = Utc.timestamp_opt(current_time.as_secs() as i64, 0).unwrap();
let beginning_of_month_date = current_date.with_day(1).unwrap();
let beginning_of_month_datetime = beginning_of_month_date
.date_naive()
.and_hms_opt(0, 0, 0)
.unwrap();
Duration::from_secs(beginning_of_month_datetime.timestamp() as u64)
}
pub fn end_of_month(current_time: Duration) -> Duration {
let current_date = Utc.timestamp_opt(current_time.as_secs() as i64, 0).unwrap();
let next_month = if current_date.month() == 12 {
current_date
.with_month(1)
.unwrap()
.with_year(current_date.year() + 1)
.unwrap()
} else {
current_date.with_month(current_date.month() + 1).unwrap()
};
let end_of_month_date = next_month.with_day(1).unwrap();
let end_of_month_datetime = end_of_month_date.date_naive().and_hms_opt(0, 0, 0).unwrap();
Duration::from_secs(end_of_month_datetime.timestamp() as u64)
}
pub fn end_of_week(time: Duration) -> Duration {
let beginning = beginning_of_week(time);
beginning + Duration::from_secs(86400 * 7)
}