Adding 15 business days to lubridate

I have a long list of start dates for a specific procedure. The rules require that the procedure be completed in no more than 6 business days. I want to calculate the deadline.

Using lubridate in R, I can get a six day deadline, this way

> library(lubridate) > date.in <- dmy(c("30-8-2001", "12-1-2003", "28-2-2003", "20-5-2004")) > date.in [1] "2001-08-30 UTC" "2003-01-12 UTC" "2003-02-28 UTC" "2004-05-20 UTC" > deadline.using.days <- date.in + days(6) > deadline.using.days [1] "2001-09-05 UTC" "2003-01-18 UTC" "2003-03-06 UTC" "2004-05-26 UTC" 

Is there an easy way to add six business days, i.e. skip Saturdays and Sundays? Thanks.

+5
source share
5 answers

The timeDate package has a great function isBizday , which made it more interesting than it seemed at first glance.

 date.in <- dmy(c("30-8-2001", "12-1-2003", "28-2-2003", "20-5-2004")) 

Here is the function to do the work. It was wise to choose 1:10 for days to look ahead, but this, of course, can be adjusted.

 deadline <- function(x) { days <- x + 1:10 Deadline <- days[isBizday(as.timeDate(days))][6] data.frame(DateIn = x, Deadline, DayOfWeek = weekdays(Deadline), TimeDiff = difftime(Deadline, x)) } 

And here is the result:

 library(timeDate) Reduce(rbind, Map(deadline, as.Date(date.in))) # DateIn Deadline DayOfWeek TimeDiff # 1 2001-08-30 2001-09-07 Friday 8 days # 2 2003-01-12 2003-01-20 Monday 8 days # 3 2003-02-28 2003-03-10 Monday 10 days # 4 2004-05-20 2004-05-28 Friday 8 days 
+5
source

The bizdays package has an offset function that shifts the given dates by the number of working days. It relies on a calendar that you define, and, of course, you can define a calendar in which weekends are the only days off.

Here is an example:

 library(lubridate) library(bizdays) cal <- Calendar(weekdays=c('saturday', 'sunday')) date.in <- dmy(c("30-8-2001", "12-1-2003", "28-2-2003", "20-5-2004")) bizdays::offset(date.in, 6, cal) # [1] "2001-09-07" "2003-01-21" "2003-03-10" "2004-05-28" 
+4
source

Try

 library(chron) date.in <- dmy(c("30-8-2001", "12-1-2003", "28-2-2003", "20-5-2004")) do.call(rbind, lapply(date.in, function(x) { x1 <-seq(as.Date(x)+1, length.out=15, by='1 day') data.frame(Start=x,End=x1[!is.weekend(x1)][6])})) # Start End #1 2001-08-30 2001-09-07 #2 2003-01-12 2003-01-20 #3 2003-02-28 2003-03-10 #4 2004-05-20 2004-05-28 

You can also check library(bizdays) to find all working days. Here, the criteria for a working day are not clear, as they may vary from country to country.

+2
source

Here's a little infix function that adds offsets on weekdays:

 `%+wday%` <- function (x, i) { if (!inherits(x, "Date")) stop("x must be of class 'Date'") if (!is.integer(i) && !is.numeric(i) && !all(i == as.integer(i))) stop("i must be coercible to integer") if ((length(x) != length(i)) && (length(x) != 1) && length(i) != 1) stop("'x' and 'i' must have equal length or lenght == 1") if (!is.integer(i)) i = as.integer(i) wd = lubridate::wday(x) saturdays <- wd == 7 sundays <- wd == 1 if (any(saturdays) || any(sundays)) warning("weekend dates are coerced to the previous Friday before applying weekday shift") x <- (x - saturdays * 1) x <- (x - sundays * 2) wd <- wd - saturdays * 1 + sundays * 5 x + 7 * (i%/%5) + i%%5 + 2 * (wd - 2 > 4 - i%%5) } 

Using:

 Sys.Date() %+wday% + 1:7 
+1
source

Here is the @ richard-craven solution --- it takes into account holidays other than weekends, which is a plus - it generalizes to a variable number of working days.

 library(lubridate) library(timeDate) bizDeadline <- function(x, nBizDys = 6){ output <- Reduce(rbind, Map((function(x, howMuch = 15){ x <- as.Date(x) days <- x + 1:(howMuch*2) Deadline <- days[isBizday(as.timeDate(days))][howMuch] data.frame(DateIn = x, Deadline, DayOfWeek = weekdays(Deadline), TimeDiff = difftime(Deadline, x)) # useful to get more info, if so wished }), x, howMuch = nBizDys)) output$Deadline } # example date.in <- dmy(c("30-8-2001", "12-1-2003", "28-2-2003", "20-5-2004")) bizDeadline(date.in, nBizDys=31) # [1] "2001-10-12" "2003-02-24" "2003-04-14" "2004-07-02" 

(An interesting extension: how do you change default = holidayNYSE with bulk holidays in the timeDate package (for example, Chile http://www.feriadoschilenos.cl/ ) "But this is another question.)

Thanks for your help!

0
source

Source: https://habr.com/ru/post/1206218/


All Articles