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::add_days; ← from dates.add-days ^1.0.0 · built alongside by fune
use super::dates_day_of_week::day_of_week; ← from dates.day-of-week ^1.0.0 · built alongside by fune
use super::subscriptions_next_billing_date::next_billing_date; ← from subscriptions.next-billing-date ^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
/// The first date of the series strictly after both `due` and `today`.
///
/// Every occurrence is the anchor plus whole intervals, so month ends stay
/// month ends; finishing late skips the occurrences already missed.
///
/// # Panics
/// Panics on an unknown frequency, an interval below 1 (or above 1 for
/// weekdays), an impossible date, or an anchor after the due date.
pub fn next_occurrence(recurrence: &Recurrence, due: &str, today: &str) -> String {
let frequency = recurrence.frequency.as_str();
let interval = recurrence.interval;
let step = match frequency {
"daily" => "day",
"weekly" => "week",
"monthly" => "month",
"yearly" => "year",
"weekdays" => "",
other => panic!(
"unknown repeat frequency \"{}\": expected daily, weekdays, weekly, monthly or yearly",
other
),
};
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);
}
add_days(&recurrence.anchor, 0);
add_days(due, 0);
add_days(today, 0);
if recurrence.anchor.as_str() > due {
panic!("repeat anchor {} is after the due date {}", recurrence.anchor, due);
}
let after = if due > today { due } else { today };
if frequency == "weekdays" {
let mut next = add_days(after, 1);
while day_of_week(&next) > 5 {
next = add_days(&next, 1);
}
return next;
}
next_billing_date(&recurrence.anchor, step, interval, after)
}
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(next_occurrence(&rule, args[1].as_str(), args[2].as_str()))
}