在R中获取当前日期的上一个月的开始日期和结束日期

35

在R中,有没有一种简单的方法可以从当前日期获取上个月的开始日期和结束日期?

我只有当前日期。我想从中获取上个月、上个月的开始日期和结束日期。

currentDate<-Sys.Date() #return today's date as "2012-11-07"

我希望从今天的日期开始,将上个月的开始日期设置为2012-10-01,结束日期设置为2012-10-31。


请发布样本数据、期望结果并展示您已经尝试过的内容。 - Andrie
7个回答

41

许多软件包具有方便的日期函数,但如果您想要自己编写:

一个月初函数:

som <- function(x) {
  as.Date(format(x, "%Y-%m-01"))
}

以及一个月末函数(虽然在这里您不需要使用它):

eom <- function(x) {
  som(som(x) + 35) - 1
}

那应该能帮助你开始。例如,要获取上个月的末尾:

som(Sys.Date()) - 1
[1] "2012-10-31"

并且月初:

som(som(Sys.Date()) - 1)
[1] "2012-10-01"

下个月的开始和结束日期呢? - BlackHat

36

使用 lubridate 很简单:

library(lubridate)
floor_date(Sys.Date() - months(1), "month")

在R语言中有很多好的库。似乎你需要的一切都已经被创建了。

更新版本:

library(lubridate)
floor_date(as.Date("2011-03-29"), "month") - months(1)

这个已经修正,可以与3月29日一起正常工作。


这个解决方案是错误的,例如 floor_date(as.Date("2011-03-29") - months(1), "month") 会返回 NA。 - André C. Andersen
Andre,你是对的。谢谢!这也适用于03-29:floor_date(as.Date("2011-03-29"), "month") - months(1) - Nikita Hismatov

19

使用lubridate包的另一个选项是使用rollback函数,正如描述所说,它会确切地执行此操作。

rollback将日期更改为上个月的最后一天或本月的第一天。新日期可以选择保留相同的小时、分钟和秒信息。

library(lubridate)

currentDate <- Sys.Date()

end_last_month <- rollback(currentDate)

init_last_month <- rollback(end_last_month, roll_to_first = TRUE)

18

你可以使用库lubridate,它非常擅长进行日期运算。

library(lubridate)

currentDate <-Sys.Date()
# end of previous month:
eopm <- currentDate - days(day(currentDate))
# [1] "2012-10-31"

# start of previous month:
sopm <- currentDate - days(day(currentDate))
sopm <- sopm - days(day(sopm) - 1)
# [1] "2012-10-01"

5

上个月开始日期:

format(Sys.Date() - 30, '%Y-%m-01')

上个月末日期:
as.Date(format(Sys.Date(), '%Y-%m-01')) - 1

那真是个聪明的人 :) - Guy Manova
有一些边缘情况可能无法正常工作。例如:format(as.Date("2022-03-01") - 30, '%Y-%m-01') - Giovanni Colitti

1
使用timeperiodsR获取任何时期的开始和结束日期。
# install.packages("timeperiodsR")
timeperiodsR::previous_month()

0

这个解决方案考虑了从"2022-03-01"减去30天时,会得到一月份而不是二月份的事实。

# Get end date of previous month
end <- (as.Date(format(Sys.Date(), "%Y-%m-01")) - 1) 

# Get start date of previous month after knowing end date
start <- as.Date(format(end, "%Y-%m-01")) 

start
#> [1] "2022-02-01"
end
#> [1] "2022-02-28"

# Works in edge cases where subtracting 30 days 
# from the current datewill not give you the previous month
date <- "2022-03-01"
end <- (as.Date(format(date, "%Y-%m-01")) - 1) 
#> Error in format.default(date, "%Y-%m-01"): invalid 'trim' argument

# Get start date of previous month after knowing end date
start <- as.Date(format(end, "%Y-%m-01")) 

start 
#> [1] "2022-02-01"
end
#> [1] "2022-02-28"

reprex包(v2.0.1)于2022-03-04创建

这里是我编写的一个函数,以更灵活的方式解决此问题,使用可变时间段(日、周、月、年)并全部在基本R中编写:

calc_previous_date_range <- function(x,
                                     time_period = c("day", "week", "month", "year"),
                                     multiplier = 1,
                                     is_complete = TRUE,
                                     week_start = 1) {
  
  time_period <- match.arg(time_period)
  
  if (multiplier == 0) stop(call. = FALSE, "`multiplier` cannot equal 0")
  
  if (time_period == "day") {
    
    if (is_complete) {
      
      start <- x - multiplier
      
      end <- x - 1
      
    } else {
      
      start <- x - (multiplier - 1)
      
      end <- x
      
    }
    
  } else if (time_period == "week") {
    
    if (is_complete) {
      
      start <- cut(x - (7 * multiplier), breaks = 'week', start.on.monday = week_start) 
      start <- as.Date(start)
      
      end <- cut(x, breaks = "week", start.on.monday = week_start) 
      end <- as.Date(end)
      
      end <- end - 1
      
    } else {
      
      start <- cut(x, breaks = 'week', start.on.monday = week_start) 
      
      if (multiplier > 0) {
        start <- as.Date(start) - (7 * (multiplier - 1)) 
      }
      
      end <- x
      
    }
    
  } else if (time_period == "month") {
    
    if (is_complete) {
      
      end <- as.Date(format(x, "%Y-%m-01")) - 1
      
      start <- as.Date(format(as.Date(end), "%Y-%m-01"))
      
      if (multiplier > 1) {
        
        old_month <- as.numeric(format(start, "%m"))
        
        old_year <- as.numeric(format(start, "%Y"))
        
        # Calc new month
        new_month <- format(seq(start, length = multiplier, by = "-1 months")[multiplier], "%m")
        
        # Calc new year
        if (multiplier >= old_month) {
          
          new_year <- old_year - (1 + floor(((multiplier - old_month) / 12)))
          
        } else {
          
          new_year <- old_year
          
        }
        
        start <- as.Date(paste0(new_year, "-", new_month, "-01")) 
        
      }
      
    } else {
      
      start <- format(x, "%Y-%m-01")
      
      start <- as.Date(start)
      
      if (multiplier > 1) {
        
        old_month <- as.numeric(format(start, "%m"))
        
        old_year <- as.numeric(format(start, "%Y"))
        
        # Calc new month
        new_month <- format(seq(start, length = multiplier, by = "-1 months")[multiplier], "%m")
        
        # Calc new year
        if (multiplier >= old_month) {
          
          new_year <- old_year - (1 + floor(((multiplier - old_month) / 12)))
          
        } else {
          
          new_year <- old_year
          
        }
        
        start <- as.Date(paste0(new_year, "-", new_month, "-01")) 
        
      }
      
      end <- x
      
    }
    
  } else if (time_period == "year") {
    
    if (is_complete) {
      
      end <- as.Date(format(x, "%Y-01-01")) - 1
      
      start <- as.Date(format(as.Date(end), paste0(as.numeric(format(end, "%Y")) - (multiplier - 1), "-01-01"))) 
      
    } else {
      
      start <- format(x, "%Y-01-01") 
      
      start <- as.Date(start)
      
      if (multiplier > 1) {
        
        old_year <- as.numeric(format(as.Date(start)))
        
        start <- format(start, old_year - (multiplier - 1), "-%m-01") 
        
        start <- as.Date(start)
        
      }
      
      end <- x
      
    }
    
  }
  
  c(start, end)
  
}

一些例子:

# Last 6 days (including partial days, i.e. today)
calc_previous_date_range(Sys.Date(), "day", 6, is_complete = FALSE)
#> [1] "2022-02-27" "2022-03-04"

# Last complete 6 days 
calc_previous_date_range(Sys.Date(), "day", 6, is_complete = TRUE)
#> [1] "2022-02-26" "2022-03-03"

# Last 3 weeks (including current week)
calc_previous_date_range(Sys.Date(), "week", 3, is_complete = FALSE)
#> [1] "2022-02-14" "2022-03-04"

# Last 3 complete weeks
calc_previous_date_range(Sys.Date(), "week", 3, is_complete = TRUE)
#> [1] "2022-02-07" "2022-02-27"

# Last 3 complete weeks where week start is Sunday instead of Monday
calc_previous_date_range(Sys.Date(), "week", 3, is_complete = TRUE, week_start = 0)
#> [1] "2022-02-06" "2022-02-26"

# Last month (including current month)
calc_previous_date_range(Sys.Date(), "month", 1, is_complete = FALSE)
#> [1] "2022-03-01" "2022-03-04"

# Last complete month
calc_previous_date_range(Sys.Date(), "month", 1, is_complete = TRUE)
#> [1] "2022-02-01" "2022-02-28"

# Last 6 complete months
# Note that the year is handled properly 
calc_previous_date_range(Sys.Date(), "month", 6, is_complete = TRUE)
#> [1] "2021-09-01" "2022-02-28"

# Last year (including current year)
calc_previous_date_range(Sys.Date(), "year", 1, is_complete = FALSE)
#> [1] "2022-03-01" "2022-03-04"

# Last year (excluding current year)
calc_previous_date_range(Sys.Date(), "year", 1, is_complete = TRUE)
#> [1] "2021-01-01" "2021-12-31"

# Last 3 years (excluding current year)
calc_previous_date_range(Sys.Date(), "year", 3, is_complete = TRUE)
#> [1] "2019-01-01" "2021-12-31"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接