use chrono::{DateTime, Duration, Utc};
use crate::entities::anniversary::Anniversary;
const SECS_PER_DAY: i64 = 86400;
const SECS_PER_WEEK: i64 = 604800;
pub struct DateService {
pub now: DateTime<Utc>,
pub fun_anniversaries_count: Vec<i64>,
}
impl DateService {
pub fn find_anniversaries_from_date(
&self,
date: DateTime<Utc>,
is_past: Option<bool>,
) -> Vec<Anniversary> {
let mut anniversaries: Vec<Anniversary> = vec![];
let mut seconds: Vec<Anniversary> =
self.create_seconds_anniversaries_from_date(date.clone());
anniversaries.append(&mut seconds);
let mut days: Vec<Anniversary> = self.create_days_anniversaries_from_date(date.clone());
anniversaries.append(&mut days);
let mut weeks: Vec<Anniversary> = self.create_weeks_anniversaries_from_date(date.clone());
anniversaries.append(&mut weeks);
if let Some(past) = is_past {
anniversaries = self.filter_anniversaries(anniversaries, past);
}
return anniversaries;
}
pub fn filter_anniversaries(
&self,
anniversaries: Vec<Anniversary>,
is_past: bool,
) -> Vec<Anniversary> {
let filtered: Vec<Anniversary>;
if is_past == true {
filtered = anniversaries
.into_iter()
.filter(|a| a.date.lt(&self.now))
.collect();
} else {
filtered = anniversaries
.into_iter()
.filter(|a| a.date.ge(&self.now))
.collect();
}
filtered
}
pub fn create_seconds_anniversaries_from_date(&self, date: DateTime<Utc>) -> Vec<Anniversary> {
let mut anniversaries: Vec<Anniversary> = vec![];
for sec in self.fun_anniversaries_count.iter() {
if let Some(_) = sec.checked_mul(1000) {
let duration = Duration::seconds(sec.to_owned() as i64);
let date = date.checked_add_signed(duration);
if let Some(d) = date {
let annif = Anniversary::new_seconds(sec.to_owned(), d);
anniversaries.push(annif);
} else {
println!("Overflow calculating seconds from {}", sec);
}
} else {
println!("Too many milliseconds in seconds");
}
}
return anniversaries;
}
pub fn create_days_anniversaries_from_date(&self, date: DateTime<Utc>) -> Vec<Anniversary> {
let mut anniversaries: Vec<Anniversary> = vec![];
for day in self.fun_anniversaries_count.iter() {
if let Some(_) = day.checked_mul(SECS_PER_DAY * 1000) {
let duration = Duration::days(day.to_owned() as i64);
let date = date.checked_add_signed(duration);
if let Some(d) = date {
let annif = Anniversary::new_days(day.to_owned(), d);
anniversaries.push(annif);
} else {
println!("Overflow calculating days from {}", day);
}
} else {
println!("Too many milliseconds in days");
}
}
return anniversaries;
}
pub fn create_weeks_anniversaries_from_date(&self, date: DateTime<Utc>) -> Vec<Anniversary> {
let mut anniversaries: Vec<Anniversary> = vec![];
for week in self.fun_anniversaries_count.iter() {
if let Some(_) = week.checked_mul(SECS_PER_WEEK * 1000) {
let duration = Duration::weeks(week.to_owned() as i64);
let date = date.checked_add_signed(duration);
if let Some(d) = date {
let annif = Anniversary::new_weeks(week.to_owned(), d);
anniversaries.push(annif);
} else {
println!("Overflow calculating weeks from {}", week);
}
} else {
println!("Too many milliseconds in weeks");
}
}
return anniversaries;
}
}
#[cfg(test)]
mod tests {
use crate::date_service::DateService;
use crate::entities::anniversary::Anniversary;
use chrono::{DateTime, TimeZone, Utc};
const TEST_HIGH: [i64; 1] = [1_000_000_000];
const TEST_MEDIUM: [i64; 3] = [666, 1_000, 10_000];
const TEST_LOW: [i64; 2] = [666, 1_000];
const TEST_ALL: [i64; 4] = [666, 1_000, 10_000, 1_000_000_000];
#[test]
fn adding_seconds() {
let now: DateTime<Utc> = Utc::now();
let date_service = DateService {
now,
fun_anniversaries_count: TEST_HIGH.to_vec(),
};
let date_start = Utc.ymd(2010, 1, 2).and_hms(3, 4, 5);
let date_expected_1_000_d_000_000_s = Utc.ymd(2041, 9, 10).and_hms(4, 50, 45);
let vec = date_service.create_seconds_anniversaries_from_date(date_start);
assert_eq!(vec[0].date, date_expected_1_000_d_000_000_s);
}
#[test]
fn adding_days() {
let now: DateTime<Utc> = Utc::now();
let date_service = DateService {
now,
fun_anniversaries_count: TEST_MEDIUM.to_vec(),
};
let date_start = Utc.ymd(2010, 1, 2).and_hms(3, 4, 5);
let date_expected_666_d = Utc.ymd(2011, 10, 30).and_hms(3, 4, 5);
let date_expected_1_000_d = Utc.ymd(2012, 9, 28).and_hms(3, 4, 5);
let date_expected_10_000_d = Utc.ymd(2037, 5, 20).and_hms(3, 4, 5);
let vec = date_service.create_days_anniversaries_from_date(date_start);
assert_eq!(vec[0].date, date_expected_666_d);
assert_eq!(vec[1].date, date_expected_1_000_d);
assert_eq!(vec[2].date, date_expected_10_000_d);
}
#[test]
fn adding_weeks() {
let now: DateTime<Utc> = Utc::now();
let date_service = DateService {
now,
fun_anniversaries_count: TEST_LOW.to_vec(),
};
let date_start = Utc.ymd(2010, 1, 2).and_hms(3, 4, 5);
let date_expected_666_w = Utc.ymd(2022, 10, 8).and_hms(3, 4, 5);
let date_expected_1_000_w = Utc.ymd(2029, 3, 3).and_hms(3, 4, 5);
let vec = date_service.create_weeks_anniversaries_from_date(date_start);
assert_eq!(vec[0].date, date_expected_666_w);
assert_eq!(vec[1].date, date_expected_1_000_w);
}
#[test]
fn filter_anniversaries_in_future() {
let date_now = Utc.ymd(2020, 1, 2).and_hms(3, 4, 5);
let date_service = DateService {
now: date_now,
fun_anniversaries_count: TEST_ALL.to_vec(),
};
let mut anniversaries: Vec<Anniversary> = vec![];
let date_expected_1_000_d_000_000_s = Utc.ymd(2041, 9, 10).and_hms(4, 50, 45);
anniversaries.push(Anniversary::new_seconds(1, date_expected_1_000_d_000_000_s));
let date_expected_666_d = Utc.ymd(2011, 10, 30).and_hms(3, 4, 5);
anniversaries.push(Anniversary::new_seconds(1, date_expected_666_d));
let date_expected_1_000_d = Utc.ymd(2012, 9, 28).and_hms(3, 4, 5);
anniversaries.push(Anniversary::new_seconds(1, date_expected_1_000_d));
let date_expected_10_000_d = Utc.ymd(2037, 5, 20).and_hms(3, 4, 5);
anniversaries.push(Anniversary::new_seconds(1, date_expected_10_000_d));
let date_expected_666_w = Utc.ymd(2022, 10, 8).and_hms(3, 4, 5);
anniversaries.push(Anniversary::new_seconds(1, date_expected_666_w));
let date_expected_1_000_w = Utc.ymd(2029, 3, 3).and_hms(3, 4, 5);
anniversaries.push(Anniversary::new_seconds(1, date_expected_1_000_w));
let vec = date_service.filter_anniversaries(anniversaries, false);
assert_eq!(vec[0].date, date_expected_1_000_d_000_000_s);
assert_eq!(vec[1].date, date_expected_10_000_d);
assert_eq!(vec[2].date, date_expected_666_w);
assert_eq!(vec[3].date, date_expected_1_000_w);
}
#[test]
fn filter_anniversaries_in_past() {
let date_now = Utc.ymd(2020, 1, 2).and_hms(3, 4, 5);
let date_service = DateService {
now: date_now,
fun_anniversaries_count: TEST_ALL.to_vec(),
};
let mut anniversaries: Vec<Anniversary> = vec![];
let date_expected_1_000_d_000_000_s = Utc.ymd(2041, 9, 10).and_hms(4, 50, 45);
anniversaries.push(Anniversary::new_seconds(1, date_expected_1_000_d_000_000_s));
let date_expected_666_d = Utc.ymd(2011, 10, 30).and_hms(3, 4, 5);
anniversaries.push(Anniversary::new_seconds(1, date_expected_666_d));
let date_expected_1_000_d = Utc.ymd(2012, 9, 28).and_hms(3, 4, 5);
anniversaries.push(Anniversary::new_seconds(1, date_expected_1_000_d));
let date_expected_10_000_d = Utc.ymd(2037, 5, 20).and_hms(3, 4, 5);
anniversaries.push(Anniversary::new_seconds(1, date_expected_10_000_d));
let date_expected_666_w = Utc.ymd(2022, 10, 8).and_hms(3, 4, 5);
anniversaries.push(Anniversary::new_seconds(1, date_expected_666_w));
let date_expected_1_000_w = Utc.ymd(2029, 3, 3).and_hms(3, 4, 5);
anniversaries.push(Anniversary::new_seconds(1, date_expected_1_000_w));
let vec = date_service.filter_anniversaries(anniversaries, true);
assert_eq!(vec[0].date, date_expected_666_d);
assert_eq!(vec[1].date, date_expected_1_000_d);
}
#[test]
fn finding_anniversaries_from_date_all() {
let date_now = Utc.ymd(2020, 1, 2).and_hms(3, 4, 5);
let date_service = DateService {
now: date_now,
fun_anniversaries_count: TEST_ALL.to_vec(),
};
let date_start = Utc.ymd(2010, 1, 2).and_hms(3, 4, 5);
let vec = date_service.find_anniversaries_from_date(date_start, None);
assert_eq!(vec.len(), 10);
}
#[test]
fn finding_anniversaries_from_date_past() {
let now: DateTime<Utc> = Utc::now();
let date_service = DateService {
now,
fun_anniversaries_count: TEST_ALL.to_vec(),
};
let date_now = Utc.ymd(2020, 1, 2).and_hms(3, 4, 5);
let date_start = Utc.ymd(2010, 1, 2).and_hms(3, 4, 5);
let vec = date_service.find_anniversaries_from_date(date_start, Some(true));
vec.into_iter()
.for_each(|a| assert_eq!(a.date.lt(&date_now), true));
}
#[test]
fn finding_anniversaries_from_date_future() {
let now: DateTime<Utc> = Utc::now();
let date_service = DateService {
now,
fun_anniversaries_count: TEST_ALL.to_vec(),
};
let date_now = Utc.ymd(2020, 1, 2).and_hms(3, 4, 5);
let date_start = Utc.ymd(2010, 1, 2).and_hms(3, 4, 5);
let vec = date_service.find_anniversaries_from_date(date_start, Some(false));
vec.into_iter()
.for_each(|a| assert_eq!(a.date.gt(&date_now), true));
}
}