First check if date is actually a working day; if it falls on a weekend or into holidays return -1 (do not take a string, otherwise the output is character).
Else, from the seq.Date starting at 01 of the respective month to the respective date, delete weekdays starting with S and those which are in a defined vector h of holidays (if defined).
Actually R is capable of this without using any packages, and much faster.
Accordingly we could define a Vectorized function like this:
f <- Vectorize(\(d, h=NULL) {
stopifnot(inherits(d, c('Date')))
stopifnot(inherits(h, c('Date', 'NULL')))
if (grepl('S', weekdays(d)) | d %in% h) {
return(-1L)
} else {
s <- seq.Date(as.Date(paste0(substr(d, 1, 7), '-01')), d, 1L)
return(length(s[!grepl('S', weekdays(s)) & !s %in% h]))
}
}, vectorize.args='d')
f(dates)
# [1] 10 21 20 -1
f(dates, holydays)
# [1] 10 21 18 -1
Note: R >= 4.1 used.
Note that in R you should always work with the required date format and probably need to convert first:
dates <- as.Date(c("12/14/2021", "01/31/2022"), format='%m/%d/%Y')
If Saturday is a working day, use 'Su' in the grepl, or actually 'Sunday' in your locale, just try weekdays(dates).
Data:
dates <- as.Date(c("2022-12-14", "2022-01-31", "2022-04-28", "2022-12-31"))
holydays <- as.Date(c("2022-01-01", "2022-04-15", "2022-04-18", "2022-05-01",
"2022-05-26", "2022-06-06", "2022-08-01", "2022-12-25",
"2022-12-26"))