Having some issues with the bizdays package, I came across this solution. I have tweaked the solutions in two way's, one is an answer to the error Marie from the comments is experiencing.
First improvement:
weekend <- c("Saturday", "Sunday")
is language dependent, so I changed it to the wday
function and use numbers to reference days. Further I added the default to make saturdays and sundays the free days and an option to include the last date or not:
library(lubridate) ## lubridate for wday function
CountWorkdays <- function(from, to, holidays = c(), free = c(7,1), include_last = FALSE) {
# Create list of all days
possible_days <- seq(from, to, "days")
# Include last? If not, remove last item.
if (!include_last) {
possible_days <- possible_days[-length(possible_days)]
}
# Count all days that are not weekend and are not holidays
return(sum(!wday(possible_days) %in% free & !possible_days %in% holidays))
}
Second improvement: If you want to use this function on a dataframe you can use mapply
, sapply
or equivalent functions, but you can also vectorise the function and make it accept vectors (then it is also usable in dplyr::mutate
function). It is important to set which arguments are considered vectors and which are not, I choose the from and to dates to be vectorised, others are considered equal for every row. (a situation where this might not be the case is when you consider contract working days per row for people the work less then five days a week).
CountWorkdaysV <- Vectorize(CountWorkdays, c("from", "to"))
This last adjustment seems to work, but I am not really sure about performance impacts so check before you adopt this function.
Hope this helps somebody who stumbles upon this older question via Google like I did.
2019, 2020, and 2021 US Federal Holidays from https://www.opm.gov/policy-data-oversight/pay-leave/federal-holidays/
holidays <- as.Date(c("2019-01-01", "2019-01-21", "2019-02-18", "2019-05-27", "2019-07-04", "2019-09-02", "2019-10-14", "2019-11-11", "2019-11-28", "2019-12-25",
"2020-01-01", "2020-01-20", "2020-02-17", "2020-05-25", "2020-07-03", "2020-09-07", "2020-10-12", "2020-11-11", "2020-11-26", "2020-12-25",
"2021-01-01", "2021-01-18", "2021-01-20", "2021-02-15", "2021-05-31", "2021-06-18", "2021-07-05", "2021-09-06", "2021-10-11", "2021-11-11", "2021-11-25", "2021-12-24"))
Example Use:
CountWorkdaysV(as.Date("2021-01-15"), as.Date("2021-01-31"), holidays = holidays, include_last = TRUE)
# 9 days