use super::funejson::Value; use super::dates_add_business_days::add_business_days; use super::dates_bank_holidays::bank_holidays; use super::dates_day_of_week::is_weekday; fn holidays_for(years: &[i64]) -> Vec { let mut out = Vec::new(); for year in years { for holiday in bank_holidays("england-and-wales", *year) { out.push(holiday.date); } } out } fn cycle_with(submission_iso: &str, after_cutoff: bool, holidays: &[String]) -> BacsCycle { let processing_day = is_weekday(submission_iso) && !holidays.iter().any(|h| h == submission_iso); let input_day = if processing_day && !after_cutoff { submission_iso.to_string() } else { add_business_days(submission_iso, 1, holidays) }; BacsCycle { processing_day: add_business_days(&input_day, 1, holidays), entry_day: add_business_days(&input_day, 2, holidays), input_day, } } /// The Bacs cycle a file joins. Bacs works on processing days - Monday to /// Friday except England and Wales bank holidays - and a file joins the cycle /// whose input day is the day it arrives, if that is a processing day and it /// arrived before the 22:30 deadline, or the next processing day otherwise. /// Processing is the next processing day and entry the one after. /// /// # Panics /// Panics on a malformed date or a year outside the published holiday data. pub fn bacs_processing_dates(submission_iso: &str, after_cutoff: bool) -> BacsCycle { // is_weekday validates the date before its year is read. is_weekday(submission_iso); let year: i64 = submission_iso[0..4].parse().unwrap(); // Only reach for next year's calendar when the cycle really runs into it, // so a December submission in the last published year still works as long // as its cycle ends inside that year. let mut cycle = cycle_with(submission_iso, after_cutoff, &holidays_for(&[year])); if cycle.entry_day[0..4] != submission_iso[0..4] { cycle = cycle_with(submission_iso, after_cutoff, &holidays_for(&[year, year + 1])); } cycle } pub fn bacs_cycle_to_value(cycle: &BacsCycle) -> Value { Value::obj(vec![ ("inputDay", Value::str(&cycle.input_day)), ("processingDay", Value::str(&cycle.processing_day)), ("entryDay", Value::str(&cycle.entry_day)), ]) } pub fn fune_vector(args: &[Value]) -> Value { bacs_cycle_to_value(&bacs_processing_dates(args[0].as_str(), args[1].as_bool())) }