Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/davisvaughan/almanac-old2
The Grammar of Schedules
https://github.com/davisvaughan/almanac-old2
Last synced: 11 days ago
JSON representation
The Grammar of Schedules
- Host: GitHub
- URL: https://github.com/davisvaughan/almanac-old2
- Owner: DavisVaughan
- License: other
- Created: 2019-09-10T14:40:13.000Z (about 5 years ago)
- Default Branch: master
- Last Pushed: 2019-09-30T12:45:42.000Z (about 5 years ago)
- Last Synced: 2024-10-09T22:11:03.315Z (28 days ago)
- Language: R
- Homepage: https://davisvaughan.github.io/almanac-old2/
- Size: 225 KB
- Stars: 1
- Watchers: 3
- Forks: 0
- Open Issues: 4
-
Metadata Files:
- Readme: README.Rmd
- License: LICENSE
Awesome Lists containing this project
README
---
output: github_document
editor_options:
chunk_output_type: console
---```{r, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>",
fig.path = "man/figures/README-",
out.width = "100%"
)
```# almanac
[![Lifecycle: experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://www.tidyverse.org/lifecycle/#experimental)
[![Travis build status](https://travis-ci.org/DavisVaughan/almanac.svg?branch=master)](https://travis-ci.org/DavisVaughan/almanac)
[![Codecov test coverage](https://codecov.io/gh/DavisVaughan/almanac/branch/master/graph/badge.svg)](https://codecov.io/gh/DavisVaughan/almanac?branch=master)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.
```{r}
library(magrittr)
library(almanac)
```## Installation
You can NOT install the released version of almanac from [CRAN](https://CRAN.R-project.org) with:
``` r
# NO! install.packages("almanac")
```And the development version from [GitHub](https://github.com/) with:
``` r
# install.packages("devtools")
devtools::install_github("DavisVaughan/almanac")
```## Events
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.
```{r}
on_25th <- on_mday(25)
on_25th
```To determine if a date falls on an event, use `event_in()`.
```{r}
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.
```{r}
event_intersect(on_25th, on_month("Nov"))
```It's often easier to use the shortcut operators `&`, `|`, and `-`.
```{r}
on_nov_25th <- on_25th & on_month("Nov")on_nov_25th
``````{r}
event_in("2019-11-24", on_nov_25th)event_in("2019-11-25", on_nov_25th)
```## Schedules
A schedule is a collection of events. You can create them by starting with an empty `schedule()`, and then adding events with `sch_add()`.
```{r}
# 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()`.
```{r}
sch_in("2019-01-01", sch)sch_in("2019-12-25", sch)
```Generate dates in the schedule with `sch_seq()`.
```{r}
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.
```{r}
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.
```{r}
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.
```{r}
# "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)
```## Acknowledgements
almanac is a combination of ideas from the date library of [QuantLib](https://github.com/lballabio/QuantLib) with the great package from James Laird-Smith, [gs](https://github.com/jameslairdsmith/gs). Both gs and almanac are based on a [paper written by Martin Fowler](https://martinfowler.com/apsupp/recurring.pdf), 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.