knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.path = "man/figures/README-", out.width = "100%" )
almanac implements a grammar of schedules, providing the fundamental rules and concepts that allow you to build up a schedule of "events", such as holidays or weekends. After creating a schedule from the fundamental rules, it can be used to:
Generate dates that fall in the schedule.
Determine if a date is in the schedule or not.
Shift a sequence of dates, stepping over or avoiding dates that fall in the schedule.
library(magrittr) library(almanac)
You can NOT install the released version of almanac from CRAN with:
# NO! install.packages("almanac")
And the development version from GitHub with:
# install.packages("devtools") devtools::install_github("DavisVaughan/almanac")
An event is a set of rules that define a reoccuring date, such as New Years Day, or the third Monday in November.
Events are created from a family of related functions that all start with one of:
on_*()
before_*()
after_*()
between_*()
For example, on_mday(25)
defines the reoccuring event of the 25th day of the month.
on_25th <- on_mday(25) on_25th
To determine if a date falls on an event, use event_in()
.
event_in("2019-01-25", on_25th) event_in("2019-01-23", on_25th) event_in("2019-02-25", on_25th)
Events can be combined by taking an intersection, a union, or a difference. Here, we take an intersection, which should be read as "the 25th of the month and the month of November" to define the event of November 25th.
event_intersect(on_25th, on_month("Nov"))
It's often easier to use the shortcut operators &
, |
, and -
.
on_nov_25th <- on_25th & on_month("Nov") on_nov_25th
event_in("2019-11-24", on_nov_25th) event_in("2019-11-25", on_nov_25th)
A schedule is a collection of events. You can create them by starting with an empty schedule()
, and then adding events with sch_add()
.
# Labor Day = First Monday in September on_labor_day <- on_month("Sep") & on_wday("Mon") & on_mweek(1) # Christmas = December 25th on_christmas <- on_month("Dec") & on_mday(25) sch <- schedule() %>% sch_add(on_labor_day, "Labor Day") %>% sch_add(on_christmas, "Christmas") sch
Check if a date is in a schedule with sch_in()
.
sch_in("2019-01-01", sch) sch_in("2019-12-25", sch)
Generate dates in the schedule with sch_seq()
.
sch_seq("2018-01-01", "2020-12-31", sch)
If you have an existing set of dates, you can adjust them relative to the schedule with sch_adjust()
. If a date happens to fall on an event in the schedule, then an adjustment
is applied repeatedly until the next non-event date is found.
x <- as.Date("2019-09-01") + 0:3 x # Labor day is the 2nd of Sept in 2019 x[sch_in(x, sch)] # Every date is left alone except 2019-09-02. The adjustment is applied as # `x + adjustment` to get to 2019-09-03. sch_adjust(x, sch, adjustment = days(1))
You can shift a set of dates relative to the schedule with sch_jump()
and sch_step()
.
Jumping applies a period shift all at once. You start at x
and end at x + jump
. If, after the jump, the date you landed on is an event, an adjustment is made to find the next non-event date.
christmas_eve <- as.Date("2019-12-24") # Jump forward 1 day - Lands on the 25th, Christmas # An adjustment of 1 day is made to shift to the 26th sch_jump(christmas_eve, jump = days(1), schedule = sch, adjustment = days(1)) # Jump forward 2 days - Lands on the 26th # No adjustment is required sch_jump(christmas_eve, jump = days(2), schedule = sch, adjustment = days(1))
In the above example, jumping forward 2 days might not have the intended result if you wanted to look forward "2 business days". In those cases, use sch_step()
. This steps 1 day at a time, and after each step checks if the date you are on is an event. If it is, it applies the adjustment
, then continues to the next step.
# "2 business days from now" # Step forward 1 day - Lands on the 25th # An adjustment of 1 day is made to shift to the 26th # Step forward 1 day - Lands on the 27th # No adjustment is required sch_step("2019-12-24", 2, sch)
almanac is a combination of ideas from the date library of QuantLib with the great package from James Laird-Smith, gs. Both gs and almanac are based on a paper written by Martin Fowler, which outlines the grammar for reoccuring events and schedules.
The hope is that gs and almanac will merge, as they currently overlap a large amount.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.