Jakub.Novotny
Jakub.Novotny

Reputation: 3047

R recursive function to add n days to a date skipping saturdays/sundays and bank holidays

I have a function that can add one day to a date. In case the following date is on Saturday/Sunday/bank holiday, the function calls itself with the argument date = date + 1 from the previous function call. Now I would like to extend the function so that it allows for adding n days (instead of 1 day that works currently). I would like to use functional programming/recursion to do that if possible.

# simplified for only 1 bank holiday on 22nd January (in reality, there are more bank holidays)
# simplified to only allow to add one day
# want to add n day(s) skipping bank holiday(s) and Saturdays/Sundays
next_bus_day_simplified <- function(.date = ymd("2021-01-21")){
  
  following_date <- .date + 1
  
  df <- data.frame(following_date) %>%
    mutate(
      following_date = case_when(
        wday(following_date, week_start = 1) %in% c(6, 7) ~ NA_Date_,
        day(following_date) ==  22 & month(following_date) ==  1 ~ NA_Date_,
        T ~ following_date
      )
    )
  
  return(
    if(!is.na(df$following_date)){ df$following_date }else{next_bus_day_simplified(following_date)}
  )
  
}

next_bus_day_simplified()
# [1] "2021-01-25"

Upvotes: 1

Views: 138

Answers (1)

Jakub.Novotny
Jakub.Novotny

Reputation: 3047

This seems to achieve what I need using recursion.

# simplified for only 1 bank holiday on 22nd January (in reality, there are more bank holidays)
# allows to add n day(s) skipping bank holiday(s) and Saturdays/Sundays
next_bus_day_simplified <- function(.date, .n){
  
  .n <- .n - 1
  following_date <- .date + 1
  
  df <- data.frame(following_date) %>%
    mutate(
      following_date = case_when(
        wday(following_date, week_start = 1) %in% c(6, 7) ~ NA_Date_,
        day(following_date) ==  22 & month(following_date) ==  1 ~ NA_Date_,
        T ~ following_date
      )
    )
  
  if(is.na(df$following_date)){
    Recall(following_date, .n + 1) # the following day is 
  }
  else if(!is.na(df$following_date) & .n > 0){
    Recall(following_date, .n = .n)
  }
  else if(!is.na(df$following_date) & .n == 0){
    return(df$following_date)
  }
  else{
    print("unexpected!!!!")
  }
}

next_bus_day_simplified(ymd("2021-01-20"), .n = 2)
# [1] "2021-01-25"

Upvotes: 1

Related Questions