簡體   English   中英

如何獲取R中月份的最后一個工作日的日期

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM