use ical::{
recur::{IcalRecurDateTime, IcalRecurRule, expand::IcalRecurExpand, set::IcalRecurSet},
tree::cst::IcalCst,
};
fn main() {
let rule = IcalRecurRule::parse("FREQ=MONTHLY;BYDAY=2TU;COUNT=4").unwrap();
let start = IcalRecurDateTime::date(2026, 1, 1);
println!("FREQ=MONTHLY;BYDAY=2TU from 2026-01-01:");
for at in IcalRecurExpand::new(rule, start) {
println!(" {}-{:02}-{:02}", at.year, at.month, at.day);
}
let raw = concat!(
"BEGIN:VCALENDAR\r\n",
"VERSION:2.0\r\n",
"PRODID:-//Example//EN\r\n",
"BEGIN:VEVENT\r\n",
"UID:standup@example.com\r\n",
"DTSTAMP:20260101T000000Z\r\n",
"DTSTART:20260105T090000\r\n",
"RRULE:FREQ=WEEKLY;COUNT=5\r\n",
"RDATE:20260108T090000\r\n",
"EXDATE:20260119T090000\r\n",
"SUMMARY:Standup\r\n",
"END:VEVENT\r\n",
"BEGIN:VEVENT\r\n",
"UID:standup@example.com\r\n",
"DTSTAMP:20260101T000000Z\r\n",
"RECURRENCE-ID:20260126T090000\r\n",
"DTSTART:20260126T140000\r\n",
"SUMMARY:Standup (moved to the afternoon)\r\n",
"END:VEVENT\r\n",
"END:VCALENDAR\r\n",
);
let cst = IcalCst::parse(raw).unwrap();
let cal = cst.decode();
let set = IcalRecurSet::of_uid(&cal.components, "standup@example.com");
println!("\nwhat the standup happens on:");
for occurrence in set.expand() {
let at = occurrence.start;
let note = match occurrence.over {
Some(_) => " (overridden)",
None => "",
};
println!(
" {}-{:02}-{:02} {:02}:{:02}{note}",
at.year, at.month, at.day, at.hour, at.minute,
);
}
println!("\nthe rule counted 5 instances, and the component then:");
println!(" added {} by RDATE", set.dates.len());
println!(" removed {} by EXDATE", set.exdates.len());
println!(" moved {} by RECURRENCE-ID", set.overrides.len());
}