The Internet Engineering Task Force (IETF) has released an exhaustive guide about how to design a calendar application. It is known as the iCalendar specification guide, RFC-5545. Recurrence rules are a small subsection of this, and the JavaScript library underlying almanac was built to comply with the specification guide. To show that almanac also complies with (pretty much all) of the guide as well, this vignette will go through the large list of examples that the guide provides to ensure that your application is doing the right thing. This will also serve as a way to show how flexible almanac is to construct a wide range of recurrence rules.
The specific section of the iCalendar guide that mentions recurrence rules is 3.3.10, and the section with all of the examples is 3.8.5.3.
For whatever reason, most examples use a start date of 1997-09-02
. To show the results, for terminating recurrence rules (those that have a limited count or an until date) I will use alma_search()
with since
as the from
date and a to
date far enough in the future to show useful results. For non-terminating rules, I will choose a to
date that shows enough to be informative, without being overwhelming.
rrule <- daily(since, until = "1997-12-24")
alma_search(since, to, rrule)
#> [1] "1997-09-02" "1997-09-03" "1997-09-04" "1997-09-05" "1997-09-06"
#> [6] "1997-09-07" "1997-09-08" "1997-09-09" "1997-09-10" "1997-09-11"
#> [11] "1997-09-12" "1997-09-13" "1997-09-14" "1997-09-15" "1997-09-16"
#> [16] "1997-09-17" "1997-09-18" "1997-09-19" "1997-09-20" "1997-09-21"
#> [21] "1997-09-22" "1997-09-23" "1997-09-24" "1997-09-25" "1997-09-26"
#> [26] "1997-09-27" "1997-09-28" "1997-09-29" "1997-09-30" "1997-10-01"
#> [31] "1997-10-02" "1997-10-03" "1997-10-04" "1997-10-05" "1997-10-06"
#> [36] "1997-10-07" "1997-10-08" "1997-10-09" "1997-10-10" "1997-10-11"
#> [41] "1997-10-12" "1997-10-13" "1997-10-14" "1997-10-15" "1997-10-16"
#> [46] "1997-10-17" "1997-10-18" "1997-10-19" "1997-10-20" "1997-10-21"
#> [51] "1997-10-22" "1997-10-23" "1997-10-24" "1997-10-25" "1997-10-26"
#> [56] "1997-10-27" "1997-10-28" "1997-10-29" "1997-10-30" "1997-10-31"
#> [61] "1997-11-01" "1997-11-02" "1997-11-03" "1997-11-04" "1997-11-05"
#> [66] "1997-11-06" "1997-11-07" "1997-11-08" "1997-11-09" "1997-11-10"
#> [71] "1997-11-11" "1997-11-12" "1997-11-13" "1997-11-14" "1997-11-15"
#> [76] "1997-11-16" "1997-11-17" "1997-11-18" "1997-11-19" "1997-11-20"
#> [81] "1997-11-21" "1997-11-22" "1997-11-23" "1997-11-24" "1997-11-25"
#> [86] "1997-11-26" "1997-11-27" "1997-11-28" "1997-11-29" "1997-11-30"
#> [91] "1997-12-01" "1997-12-02" "1997-12-03" "1997-12-04" "1997-12-05"
#> [96] "1997-12-06" "1997-12-07" "1997-12-08" "1997-12-09" "1997-12-10"
#> [101] "1997-12-11" "1997-12-12" "1997-12-13" "1997-12-14" "1997-12-15"
#> [106] "1997-12-16" "1997-12-17" "1997-12-18" "1997-12-19" "1997-12-20"
#> [111] "1997-12-21" "1997-12-22" "1997-12-23" "1997-12-24"
rrule <- daily(since) %>%
recur_on_interval(2)
alma_search(since, "1997-10-01", rrule)
#> [1] "1997-09-02" "1997-09-04" "1997-09-06" "1997-09-08" "1997-09-10"
#> [6] "1997-09-12" "1997-09-14" "1997-09-16" "1997-09-18" "1997-09-20"
#> [11] "1997-09-22" "1997-09-24" "1997-09-26" "1997-09-28" "1997-09-30"
rrule <- daily(since = "1998-01-01", until = "2000-01-31") %>%
recur_on_ymonth("January")
alma_search(since, to, rrule)
#> [1] "1998-01-01" "1998-01-02" "1998-01-03" "1998-01-04" "1998-01-05"
#> [6] "1998-01-06" "1998-01-07" "1998-01-08" "1998-01-09" "1998-01-10"
#> [11] "1998-01-11" "1998-01-12" "1998-01-13" "1998-01-14" "1998-01-15"
#> [16] "1998-01-16" "1998-01-17" "1998-01-18" "1998-01-19" "1998-01-20"
#> [21] "1998-01-21" "1998-01-22" "1998-01-23" "1998-01-24" "1998-01-25"
#> [26] "1998-01-26" "1998-01-27" "1998-01-28" "1998-01-29" "1998-01-30"
#> [31] "1998-01-31" "1999-01-01" "1999-01-02" "1999-01-03" "1999-01-04"
#> [36] "1999-01-05" "1999-01-06" "1999-01-07" "1999-01-08" "1999-01-09"
#> [41] "1999-01-10" "1999-01-11" "1999-01-12" "1999-01-13" "1999-01-14"
#> [46] "1999-01-15" "1999-01-16" "1999-01-17" "1999-01-18" "1999-01-19"
#> [51] "1999-01-20" "1999-01-21" "1999-01-22" "1999-01-23" "1999-01-24"
#> [56] "1999-01-25" "1999-01-26" "1999-01-27" "1999-01-28" "1999-01-29"
#> [61] "1999-01-30" "1999-01-31" "2000-01-01" "2000-01-02" "2000-01-03"
#> [66] "2000-01-04" "2000-01-05" "2000-01-06" "2000-01-07" "2000-01-08"
#> [71] "2000-01-09" "2000-01-10" "2000-01-11" "2000-01-12" "2000-01-13"
#> [76] "2000-01-14" "2000-01-15" "2000-01-16" "2000-01-17" "2000-01-18"
#> [81] "2000-01-19" "2000-01-20" "2000-01-21" "2000-01-22" "2000-01-23"
#> [86] "2000-01-24" "2000-01-25" "2000-01-26" "2000-01-27" "2000-01-28"
#> [91] "2000-01-29" "2000-01-30" "2000-01-31"
rrule <- weekly(since, until = "1997-12-24")
alma_search(since, to, rrule)
#> [1] "1997-09-02" "1997-09-09" "1997-09-16" "1997-09-23" "1997-09-30"
#> [6] "1997-10-07" "1997-10-14" "1997-10-21" "1997-10-28" "1997-11-04"
#> [11] "1997-11-11" "1997-11-18" "1997-11-25" "1997-12-02" "1997-12-09"
#> [16] "1997-12-16" "1997-12-23"
rrule <- weekly(since = "1997-09-01", until = "1997-12-24") %>%
recur_on_wday(c("Mon", "Wed", "Fri")) %>%
recur_on_interval(2)
alma_search("1997-09-01", to, rrule)
#> [1] "1997-09-01" "1997-09-03" "1997-09-05" "1997-09-15" "1997-09-17"
#> [6] "1997-09-19" "1997-09-29" "1997-10-01" "1997-10-03" "1997-10-13"
#> [11] "1997-10-15" "1997-10-17" "1997-10-27" "1997-10-29" "1997-10-31"
#> [16] "1997-11-10" "1997-11-12" "1997-11-14" "1997-11-24" "1997-11-26"
#> [21] "1997-11-28" "1997-12-08" "1997-12-10" "1997-12-12" "1997-12-22"
#> [26] "1997-12-24"
Note that the day of the month is taken from the since
date, since it is not otherwise specified!
rrule <- yearly("1997-03-10") %>%
recur_on_ymonth(c("Jan", "Feb", "Mar")) %>%
recur_on_interval(2) %>%
recur_for_count(10)
alma_search("1997-03-10", to, rrule)
#> [1] "1997-03-10" "1999-01-10" "1999-02-10" "1999-03-10" "2001-01-10"
#> [6] "2001-02-10" "2001-03-10" "2003-01-10" "2003-02-10" "2003-03-10"
Default week start in almanac is on Monday.
rrule <- yearly("1997-03-13") %>%
recur_on_wday("Thursday") %>%
recur_on_ymonth("March")
alma_search("1997-03-13", "2000-01-01", rrule)
#> [1] "1997-03-13" "1997-03-20" "1997-03-27" "1998-03-05" "1998-03-12"
#> [6] "1998-03-19" "1998-03-26" "1999-03-04" "1999-03-11" "1999-03-18"
#> [11] "1999-03-25"
rrule <- yearly("1997-06-05") %>%
recur_on_wday("Thursday") %>%
recur_on_ymonth(c("Jun", "July", "Aug"))
alma_search("1997-06-05", "1999-01-01", rrule)
#> [1] "1997-06-05" "1997-06-12" "1997-06-19" "1997-06-26" "1997-07-03"
#> [6] "1997-07-10" "1997-07-17" "1997-07-24" "1997-07-31" "1997-08-07"
#> [11] "1997-08-14" "1997-08-21" "1997-08-28" "1998-06-04" "1998-06-11"
#> [16] "1998-06-18" "1998-06-25" "1998-07-02" "1998-07-09" "1998-07-16"
#> [21] "1998-07-23" "1998-07-30" "1998-08-06" "1998-08-13" "1998-08-20"
#> [26] "1998-08-27"
recur_on_position()
is an incredibly powerful tool, allowing you to select a position within the frequency. So this selects the third element of each monthly set, where the monthly set contains all of the Tuesday, Wednesday, and Thursdays of the month.
rrule <- monthly("1997-09-29") %>%
recur_on_wday(1:5) %>%
recur_on_position(-2)
alma_search("1997-09-29", "1998-12-01", rrule)
#> [1] "1997-09-29" "1997-10-30" "1997-11-27" "1997-12-30" "1998-01-29"
#> [6] "1998-02-26" "1998-03-30" "1998-04-29" "1998-05-28" "1998-06-29"
#> [11] "1998-07-30" "1998-08-28" "1998-09-29" "1998-10-29" "1998-11-27"
rrule <- weekly("1997-08-05") %>%
recur_on_interval(2) %>%
recur_for_count(4) %>%
recur_on_wday(c("Tue", "Sun")) %>%
recur_with_week_start("Monday")
# Week 1: 1997-08-04 -> 1997-08-10
# Week 2: 1997-08-11 -> 1997-08-17 (skipped)
# Week 3: 1997-08-18 -> 1997-08-24
alma_search("1997-08-05", "1998-12-01", rrule)
#> [1] "1997-08-05" "1997-08-10" "1997-08-19" "1997-08-24"
Changing the week start to Sunday.
rrule <- weekly("1997-08-05") %>%
recur_on_interval(2) %>%
recur_for_count(4) %>%
recur_on_wday(c("Tue", "Sun")) %>%
recur_with_week_start("Sunday")
# Week 1: 1997-08-03 -> 1997-08-09
# Week 2: 1997-08-10 -> 1997-08-16 (skipped)
# Week 3: 1997-08-17 -> 1997-08-23
# Week 4: 1997-08-24 -> 1997-08-30 (skipped)
# Week 5: 1997-08-31 -> 1997-09-06
alma_search("1997-08-05", "1998-12-01", rrule)
#> [1] "1997-08-05" "1997-08-17" "1997-08-19" "1997-08-31"
Invalid dates do not decrease the total count.