{"id":13400574,"url":"https://github.com/DavisVaughan/almanac","last_synced_at":"2025-03-14T06:31:44.831Z","repository":{"id":56936274,"uuid":"208673066","full_name":"DavisVaughan/almanac","owner":"DavisVaughan","description":"Tools for working with recurrence rules, holidays, and calendars","archived":false,"fork":false,"pushed_at":"2023-04-19T19:08:04.000Z","size":3045,"stargazers_count":72,"open_issues_count":2,"forks_count":4,"subscribers_count":6,"default_branch":"main","last_synced_at":"2024-10-09T22:09:29.945Z","etag":null,"topics":["calendars","holidays","r","recurrence-rules"],"latest_commit_sha":null,"homepage":"https://davisvaughan.github.io/almanac/","language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DavisVaughan.png","metadata":{"files":{"readme":"README.Rmd","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2019-09-15T23:45:27.000Z","updated_at":"2024-08-25T10:55:21.000Z","dependencies_parsed_at":"2024-01-18T11:03:42.958Z","dependency_job_id":"74a2f674-af1b-400c-9abc-c7922a7631d6","html_url":"https://github.com/DavisVaughan/almanac","commit_stats":{"total_commits":404,"total_committers":2,"mean_commits":202.0,"dds":"0.0024752475247524774","last_synced_commit":"7b14f6e8f1e685975231e5dadb40bb5bb8f2a9c8"},"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DavisVaughan%2Falmanac","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DavisVaughan%2Falmanac/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DavisVaughan%2Falmanac/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DavisVaughan%2Falmanac/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DavisVaughan","download_url":"https://codeload.github.com/DavisVaughan/almanac/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221440198,"owners_count":16821600,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["calendars","holidays","r","recurrence-rules"],"created_at":"2024-07-30T19:00:53.485Z","updated_at":"2025-03-14T06:31:44.824Z","avatar_url":"https://github.com/DavisVaughan.png","language":"R","funding_links":[],"categories":["R"],"sub_categories":[],"readme":"---\noutput: github_document\neditor_options: \n  chunk_output_type: console\n---\n\n\u003c!-- README.md is generated from README.Rmd. Please edit that file --\u003e\n\n```{r, include = FALSE}\nknitr::opts_chunk$set(\n  collapse = TRUE,\n  comment = \"#\u003e\",\n  fig.path = \"man/figures/README-\",\n  out.width = \"100%\"\n)\n```\n\n# almanac\n\n\u003c!-- badges: start --\u003e\n\n[![Codecov test coverage](https://codecov.io/gh/DavisVaughan/almanac/branch/main/graph/badge.svg)](https://app.codecov.io/gh/DavisVaughan/almanac?branch=main) [![R-CMD-check](https://github.com/DavisVaughan/almanac/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/DavisVaughan/almanac/actions/workflows/R-CMD-check.yaml)\n\n\u003c!-- badges: end --\u003e\n\n```{r}\nlibrary(almanac)\n```\n\nalmanac provides tools for working with recurrence rules, the fundamental building blocks used to identify calendar \"events\", such as weekends or holidays.\n\nAdditionally, it provides a full suite of tools for working with holidays and calendars.\nIt includes a number of built in holidays, such as `hol_christmas()`, but you can also add your own custom holidays through `rholiday()`.\nOnce you have a set of holidays specific to your business, you can aggregate them into a calendar with `rcalendar()`, which has specialized tooling like `cal_events()` to generate the holiday dates for a particular year.\n\n## Installation\n\nInstall the released version of almanac from CRAN with:\n\n``` r\ninstall.packages(\"almanac\")\n```\n\nInstall the development version from [GitHub](https://github.com/) with:\n\n``` r\n# install.packages(\"pak\")\npak::pak(\"DavisVaughan/almanac\")\n```\n\n## Recurrence rules\n\nConstructing recurrence rules looks like this:\n\n```{r}\n# Thanksgiving = \"The fourth Thursday in November\"\non_thanksgiving \u003c- yearly() %\u003e% \n  recur_on_month_of_year(\"November\") %\u003e%\n  recur_on_day_of_week(\"Thursday\", nth = 4)\n\non_thanksgiving\n```\n\nThis is the underlying recurrence rule for the Thanksgiving holiday represented by `hol_us_thanksgiving()`.\n\nAfter constructing a recurrence rule, it can be used to generate dates that are in the \"event set\".\nFor example, you can search for all Thanksgivings between 2000-2006.\n\n```{r}\nalma_events(on_thanksgiving, year = 2000:2006)\n```\n\nDetermine if a particular date is a part of the event set with `alma_in()`.\n\n```{r}\n# Is this a Thanksgiving?\nalma_in(c(\"2000-01-01\", \"2000-11-23\"), on_thanksgiving)\n```\n\nYou can also shift an existing sequence of dates, \"stepping over\" dates that are part of the event set.\n\n```{r}\nwednesday_before_thanksgiving \u003c- as.Date(\"2000-11-22\")\n\n# Thanksgiving was on 2000-11-23.\n# This steps over Thanksgiving to 2000-11-24.\n# Then steps 1 more day to 2000-11-25.\nalma_step(wednesday_before_thanksgiving, n = 2, on_thanksgiving)\n```\n\nThere is an additional \"stepper\" object you can create for more intuitive stepping.\nCombine it with `%s+%` to perform the same step done by `alma_step()`.\nCreate a stepper function with `stepper()`, and then use it by supplying the number of days to step.\n\n```{r}\nstep_over_thanksgiving \u003c- stepper(on_thanksgiving)\nwednesday_before_thanksgiving %s+% step_over_thanksgiving(2)\n```\n\n## Holidays and calendars\n\nThe above example just scratches the surface of what almanac can do.\nPractically speaking, you'll probably have multiple holidays that you'd like to combine into one big calendar.\nalmanac provides a full API for working with holidays and calendars.\n\nThis example creates a calendar containing Christmas, Thanksgiving, and New Year's Day:\n\n```{r}\ncal \u003c- rcalendar(\n  hol_christmas(),\n  hol_us_thanksgiving(),\n  hol_new_years_day()\n)\n\ncal\n```\n\nWe can ask for the next upcoming holiday with `cal_next()`:\n\n```{r}\nx \u003c- as.Date(c(\"2019-12-05\", \"2020-02-05\"))\ncal_next(x, cal)\n```\n\nOr for holidays that belong to a particular year with `cal_events()`:\n\n```{r}\nevents \u003c- cal_events(cal, year = 2028)\nevents$weekday \u003c- lubridate::wday(events$date, label = TRUE)\nevents\n```\n\nNote that New Year's Day occurred on Saturday.\nIf your business *observes* New Year's Day on the nearest weekday, you can adjust the holiday to respect that observance rule before adding it into the calendar:\n\n```{r}\non_weekends \u003c- weekly() %\u003e%\n  recur_on_weekends()\n\ncal \u003c- rcalendar(\n  hol_christmas(),\n  hol_us_thanksgiving(),\n  hol_observe(\n    hol_new_years_day(), \n    adjust_on = on_weekends, \n    adjustment = adj_nearest\n  )\n)\n\n# Now it returns the previous Friday for the observed New Year's date.\n# Note that this fell in 2027, but was included in the 2028 set of dates\n# since most people would consider that part of the 2028 holiday calendar.\nevents \u003c- cal_events(cal, year = 2028)\nevents$weekday \u003c- lubridate::wday(events$date, label = TRUE)\nevents\n```\n\nWe can union our calendar with the `on_weekends` rule to get a recurrence set that represents days when our business is closed.\nThen we can create a stepper out of that so we can step forwards by \"a business day.\"\n\n```{r}\nbusiness_day \u003c- stepper(runion(cal, on_weekends))\n```\n\nFor example, Christmas was on a Monday in 2006.\nIf you wanted to step 1 business day forward from the Friday before Christmas, you'd probably like it to step over the weekend and the Christmas Monday to finally land on Tuesday:\n\n```{r}\n# Christmas was on a Monday in 2006.\n# This is the Friday before Christmas\nfriday \u003c- as.Date(\"2006-12-22\")\n\n# Step forward 1 business day, going over the weekend and Christmas\nfriday %s+% business_day(1)\n```\n\n## Learning more\n\nView the vignettes on [the website](https://davisvaughan.github.io/almanac/index.html) to learn more about how to use almanac.\n\n-   `vignette(\"almanac\")`\n\n-   `vignette(\"holidays-calendars\")`\n\n-   `vignette(\"adjust-and-shift\")`\n\n-   `vignette(\"quarterly\")`\n\n-   `vignette(\"icalendar\")`\n\n## Acknowledgements\n\nalmanac has developed as a composite of ideas from multiple different libraries.\n\nFirst off, it directly embeds the *amazing* JavaScript library [rrule](https://github.com/jakubroztocil/rrule) for the core event set calculations.\nTo do this, it uses the equally awesome R package, [V8](https://github.com/jeroen/V8), from Jeroen Ooms.\n\nThe date shifting / adjusting functions are modeled after similar functions in [QuantLib](https://github.com/lballabio/QuantLib).\n\nThe fast binary search based implementations of `alma_next()` and `alma_step()` are inspired by Pandas and the implementation of Numpy's [busday_offset()](https://numpy.org/doc/stable/reference/generated/numpy.busday_offset.html).\n\nThe author of [gs](https://github.com/jameslairdsmith/gs), James Laird-Smith, has been a great collaborator as we have bounced ideas off of each other.\ngs attempts to solve a similar problem, but with a slightly different implementation.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FDavisVaughan%2Falmanac","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FDavisVaughan%2Falmanac","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FDavisVaughan%2Falmanac/lists"}