use super::funejson::Value; use super::dates_add_days::add_days; use super::finance_uk_bank_rate_data::{BANK_RATE, BANK_RATE_HISTORY}; /// Bank Rate in force on a date: the latest change on or before it. /// /// # Panics /// Panics on a malformed date or one before the data begins. pub fn uk_bank_rate(on_date: &str) -> BankRate { add_days(on_date, 0); // validates the date; ISO dates then compare as strings for row in BANK_RATE { if on_date >= row.valid_from && row.valid_to.map_or(true, |to| on_date <= to) { return BankRate { basis_points: row.basis_points, valid_from: row.valid_from.to_string(), valid_to: row.valid_to.map(str::to_string), }; } } // A history=current build keeps only the rate in force; answering an older // date with it would be exactly the wrong answer this data exists to prevent. if BANK_RATE_HISTORY != "full" { if let Some(earliest) = BANK_RATE.iter().map(|r| r.valid_from).min() { if on_date < earliest { panic!( "no Bank Rate on {}: this build was installed with history={}, so it only carries rates from {}. Reinstall with history=full for older dates.", on_date, BANK_RATE_HISTORY, earliest ); } } } panic!("no Bank Rate on {}", on_date); } pub fn bank_rate_to_value(rate: &BankRate) -> Value { Value::obj(vec![ ("basisPoints", Value::Int(rate.basis_points)), ("validFrom", Value::str(&rate.valid_from)), ("validTo", rate.valid_to.as_deref().map_or(Value::Null, Value::str)), ]) } pub fn fune_vector(args: &[Value]) -> Value { bank_rate_to_value(&uk_bank_rate(args[0].as_str())) }