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_add_days::parse_iso_date; ← from dates.add-days ^1.0.0 · built alongside by fune
use super::dates_day_of_week::day_name; ← from dates.day-of-week ^1.0.0 · built alongside by fune
use super::todo_item::{recurrence_from_value, Recurrence}; ← from todo.item ^1.0.0 · built alongside by fune
const MONTHS: [&str; 12] = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
/// 1st, 2nd, 3rd, 4th ... 11th, 12th, 13th ... 21st, 22nd, 23rd ... 31st.
fn ordinal(n: i64) -> String {
if (11..=13).contains(&(n % 100)) {
return format!("{}th", n);
}
let suffix = match n % 10 {
1 => "st",
2 => "nd",
3 => "rd",
_ => "th",
};
format!("{}{}", n, suffix)
}
fn every(interval: i64, unit: &str) -> String {
if interval == 1 {
format!("Every {}", unit)
} else {
format!("Every {} {}s", interval, unit)
}
}
/// English words for a repeat rule; the weekday, day and date come from the anchor.
///
/// # Panics
/// Panics on an unknown frequency, an interval below 1 (or other than 1 for
/// weekdays), or an anchor that is not a real ISO date.
pub fn recurrence_label(recurrence: &Recurrence) -> String {
let frequency = recurrence.frequency.as_str();
let interval = recurrence.interval;
if !["daily", "weekdays", "weekly", "monthly", "yearly"].contains(&frequency) {
panic!(
"unknown repeat frequency \"{}\": expected daily, weekdays, weekly, monthly or yearly",
frequency
);
}
if interval < 1 {
panic!("repeat interval must be 1 or more, received {}", interval);
}
if frequency == "weekdays" && interval != 1 {
panic!("weekday repeats cannot skip weeks: interval must be 1, received {}", interval);
}
let date = parse_iso_date(&recurrence.anchor);
match frequency {
"daily" => every(interval, "day"),
"weekdays" => "Every weekday".to_string(),
"weekly" => format!("{} on {}", every(interval, "week"), day_name(&recurrence.anchor)),
"monthly" => format!("{} on the {}", every(interval, "month"), ordinal(date.day)),
_ => format!("{} on {} {}", every(interval, "year"), date.day, MONTHS[(date.month - 1) as usize]),
}
}
pub fn fune_vector(args: &[Value]) -> Value {
if let Value::Float(f) = args[0].get("interval") {
panic!("repeat interval must be 1 or more, received {}", f);
}
let rule = recurrence_from_value(&args[0]).expect("a recurrence");
Value::Str(recurrence_label(&rule))
}