7

I need to find all 'next friday' corresponding to a set of dates.

For instance 2015-08-03 (Monday 3rd, August, 2015) as an input should return 2015-08-07 (Friday 7th, August, 2015) as an output.

I could not find a way to manage this need while reading lubridate's vignette, how would you proceed?

library(lubridate) 
date <- "2015-08-03"
date <- wmd(date)
wday(date, label = TRUE)
cho7tom
  • 1,030
  • 2
  • 13
  • 30
  • 2
    Have you read http://stackoverflow.com/questions/28971638/r-obtaining-last-fridays-date ? – lukeA Sep 07 '15 at 08:56

5 Answers5

7

Try this function:

nextweekday <- function(date, wday) {
  date <- as.Date(date)
  diff <- wday - wday(date)
  if( diff < 0 )
    diff <- diff + 7
  return(date + diff)
}

You insert your date and the desired wday (Sunday = 1, Monday = 2, ...) and get the result you wanted.

Kirill
  • 391
  • 1
  • 7
6
library(lubridate) 

nextFriday <- function(date) {
  date <- ymd(date)
  .day <- wday(date, label = TRUE)
  shift <- ifelse(as.numeric(.day) < 6, 0, 7)
  date + days(6 - as.numeric(.day) + shift)
}

nextFriday("2015-08-03")
redmode
  • 4,821
  • 1
  • 25
  • 30
  • Thanks to smart use of `ifelse`, this function works if `date` is a vector of length > 1. This should be the accepted answer. – DomQ Mar 09 '23 at 11:21
1

Lubridate provides a nice function duration. You can use this to add days to the current date.

It's generally better not to create a variable with the same name as a function (i.e. date).

the_date <- "2015-08-03"
the_date <- ymd(the_date)
wday(the_date, label = TRUE)

next_friday <- function(given_date){
  n_days_to_fri <- 6 - wday(given_date)
  z <- given_date + duration(n_days_to_fri, "days")
  return(z)
}

next_friday(the_date)
[1] "2015-08-07 UTC"
wday(next_friday(the_date), label = TRUE)
[1] Fri
Levels: Sun < Mon < Tues < Wed < Thurs < Fri < Sat
r.bot
  • 5,309
  • 1
  • 34
  • 45
1

Modification of Kiril's code.

The code does not work if I want to apply it to a vector already in dateformat in tibble format, so here is a minor tweak of your code for this:

nextweekday <- function(fdate, wk_day) {
diff <- wk_day- wday(fdate)
diff=if_else(diff<0,diff+7,diff)
return(fdate + diff)
}
General Grievance
  • 4,555
  • 31
  • 31
  • 45
0

You can also do it with modulo and integer division.

For example, for Fridays, check the following:

library(lubridate)

next_friday <- function(dates) {
  dates + days((5 - wday(dates) %% 6) + (wday(dates) %/% 6))
}

So for example:

> dates <- sample(seq(ymd('2020-01-01'),ymd('2021-01-01'), by='days'), 20)
> dates
 [1] "2020-06-28" "2020-03-22" "2020-07-15" "2020-01-16" "2020-08-01" "2020-05-16" "2020-10-20" "2020-11-03"
 [9] "2020-08-25" "2020-10-07" "2020-04-18" "2020-12-11" "2020-05-20" "2020-08-09" "2020-01-10" "2020-05-21"
[17] "2020-10-24" "2020-03-06" "2020-05-19" "2020-09-08"

> next_friday(dates)
 [1] "2020-07-02" "2020-03-26" "2020-07-16" "2020-01-16" "2020-08-06" "2020-05-21" "2020-10-22" "2020-11-05"
 [9] "2020-08-27" "2020-10-08" "2020-04-23" "2020-12-17" "2020-05-21" "2020-08-13" "2020-01-16" "2020-05-21"
[17] "2020-10-29" "2020-03-12" "2020-05-21" "2020-09-10"

> wday(next_friday(dates))
 [1] 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5


hallvig
  • 198
  • 1
  • 1
  • 6