[英]How to get date of last business day of month in R
我需要从当前日期开始使用R获取上个月的最后一个工作日(例如,今天是5th of January 2018
,因此我应该得到29th of December 2017
)
提前致谢
您需要一个工作日计算器。 在这里,我使用来自RQuantLib的一个CRAN包。
给定日期,您可以在给定的(交换)日历中测试是否是工作日。 然后,您只需按所需时间段子集即可。 使用data.table这样会更容易,但是我在这里将其简化,以便我们仅依赖于一个包:
R> library(RQuantLib)
R> dateseq <- seq(as.Date("2017-12-01"), as.Date("2017-12-31"), by="1 day")
R> df <- data.frame(dates=dateseq, bizday=isBusinessDay("UnitedStates", dateseq))
R> tail(df[ df[,"bizday"], ], 1)
dates bizday
29 2017-12-29 TRUE
R>
R> tail(df[ df[,"bizday"], "dates"], 1)
[1] "2017-12-29"
R>
您可以编写自己的函数以找出最近的工作日。 您需要定义一周的off days
才能做出决定。
# Off days
offdays <- c("Saturday", "Sunday")
# Say you want to find out last working date of December 2017
monthdates <- seq(as.Date("2017-12-01"), as.Date("2017-12-31"), by="1 day")
#Eliminate off days
monthdates<- monthdates[! weekdays(monthdates) %in% offdays]
#Find out max date in vector now
lastworkingday <- max(monthdates)
#> lastworkingday
#[1] "2017-12-29"
考虑到周末和节假日之间的相互作用,很难对此向量进行矢量化和快速处理,即
您临近月底的假期可能会将您带入临近月底的周末
一个在月末的周末可能会使您进入月末的假期
# get these packages
require(lubridate)
require(tidyverse)
calc_business_monthends<- function(dates = NULL,
holidays = NULL,
prior_month = FALSE){
# terminate early
if (length(dates) == 0) return(dates)
# make dates into prior monthend dates
in_dates<- rollback(dates)
# or make dates into current monthend dates
if(!prior_month) in_dates<- rollback((in_dates + 1) + months(1))
# inner function to recursively check dates and step backward if monthend falls on a holiday or weekend
step_back<- function(in_dates, holidays) {
# correct for Sun or Sat
out_dates<-
case_when(wday(in_dates) == 7 ~ in_dates - 1,
wday(in_dates) == 1 ~ in_dates - 2,
TRUE ~ in_dates)
# correct for holidays
if(!is.null(holidays)){
out_dates<-
if_else(out_dates %in% holidays, out_dates - 1, false = out_dates)
}
# if no weekend or holiday changes, we're done; otherwise recurse
if(identical(out_dates,in_dates)){
out_dates
} else {
step_back(out_dates, holidays)
}
} # inner-function end
# call inner-function
step_back(in_dates, holidays)
}
然后,只需将您想要的任何日期和假期传递给函数即可。
以下是一些测试:
Some example dates:
dates<- seq(ymd(20190105), by='month', length.out = 24)
Some holidays near monthend:
holidays<- ymd(20190527,20200525,20210531,20220530,20230529,20240527)
Output:
> calc_business_monthends(dates, holidays)
[1] "2019-01-31" "2019-02-28" "2019-03-29" "2019-04-30"
[5] "2019-05-31" "2019-06-28" "2019-07-31" "2019-08-30"
[9] "2019-09-30" "2019-10-31" "2019-11-29" "2019-12-31"
[13] "2020-01-31" "2020-02-28" "2020-03-31" "2020-04-30"
[17] "2020-05-29" "2020-06-30" "2020-07-31" "2020-08-31"
[21] "2020-09-30" "2020-10-30" "2020-11-30" "2020-12-31"
> calc_business_monthends(dates, holidays, prior_month = TRUE)
[1] "2018-12-31" "2019-01-31" "2019-02-28" "2019-03-29"
[5] "2019-04-30" "2019-05-31" "2019-06-28" "2019-07-31"
[9] "2019-08-30" "2019-09-30" "2019-10-31" "2019-11-29"
[13] "2019-12-31" "2020-01-31" "2020-02-28" "2020-03-31"
[17] "2020-04-30" "2020-05-29" "2020-06-30" "2020-07-31"
[21] "2020-08-31" "2020-09-30" "2020-10-30" "2020-11-30"
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.