Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.
use super::funejson::Value; ← the fune runtime: the JSON value the test vectors use; fune build keeps it only where a signature takes one
use super::dates_bank_holidays_data::BANK_HOLIDAYS; ← this capability’s own data, compiled from data/bank-holidays.json into the same file by fune build
/// The bank holidays for a UK region and year, in date order, as gov.uk
/// publishes them. A year the data does not cover is an error rather than an
/// empty list, because an empty list reads as "no holidays" and a deadline
/// calculation would then count Christmas Day as a working day.
///
/// # Panics
/// Panics on an unknown region or a year outside the published calendar.
pub fn bank_holidays(region: &str, year: i64) -> Vec<BankHoliday> {
let mut first: Option<i64> = None;
let mut last: Option<i64> = None;
let mut found: Vec<BankHoliday> = Vec::new();
let prefix = format!("{:04}-", year);
for row in BANK_HOLIDAYS {
if row.region != region {
continue;
}
let row_year: i64 = row.date[0..4].parse().unwrap();
if first.map_or(true, |f| row_year < f) {
first = Some(row_year);
}
if last.map_or(true, |l| row_year > l) {
last = Some(row_year);
}
if row.date.starts_with(&prefix) {
found.push(BankHoliday {
date: row.date.to_string(),
title: row.title.to_string(),
substitute: row.substitute,
});
}
}
let (first, last) = match (first, last) {
(Some(f), Some(l)) => (f, l),
_ => panic!(
"unknown region \"{}\": expected england-and-wales, scotland or northern-ireland",
region
),
};
if year < first || year > last {
panic!(
"no bank holiday data for {} in {}: the published calendar covers {} to {}",
region, year, first, last
);
}
// ISO dates sort correctly as strings.
found.sort_by(|a, b| a.date.cmp(&b.date));
found
}
pub fn bank_holiday_to_value(holiday: &BankHoliday) -> Value {
Value::obj(vec![
("date", Value::str(&holiday.date)),
("title", Value::str(&holiday.title)),
("substitute", Value::Bool(holiday.substitute)),
])
}
pub fn fune_vector(args: &[Value]) -> Value {
// Refuse what the typed signature cannot hold, with the wording TypeScript
// and Python use, rather than let the conversion below quietly change it.
if let Value::Float(f) = args[1] {
if f.fract() != 0.0 {
panic!("year must be an integer, received {}", f);
}
}
Value::Arr(
bank_holidays(args[0].as_str(), args[1].as_i64())
.iter()
.map(bank_holiday_to_value)
.collect(),
)
}