Search code examples
rdate-arithmeticlubridate

End of previous quarter / last day of previous quarter


Using lubridate, how to calculate the last day of the previous quarter for a given date? The below formula doesn't seem to work for Nov 3rd, 2014 (other dates work)

library(lubridate)
date = as.POSIXct("2014-11-03")
date - days(day(date)) - months(month(date) %% 3 - 1)
# NA

Interesting enough, changing order works:

date - months(month(date) %% 3 - 1) - days(day(date))
# "2014-09-30 UTC"

Solution

  • Here are some possibilities with functions from packages zoo and timeDate, and base R. The zoo code was improved by @G.Grothendieck, and he also suggested the base alternative (thanks a lot!). I leave the lubridate solution(s) to someone else.

    First, use class yearqtr in package zoo to represent the quarterly data. You may then use as.Date.yearqtr and the frac argument "which is a number between 0 and 1 inclusive that indicates the fraction of the way through the period that the result represents. The default is 0 which means the beginning of the period" (see ?yearqtr, and ?yearmon for frac).

    Step by step:

    library(zoo)
    
    date <- as.Date("2014-11-03")
    
    # current quarter
    current_q <- as.yearqtr(date)
    current_q
    # [1] "2014 Q4"
    
    # first date in current quarter
    first_date_current_q <- as.Date(current_q, frac = 0)
    first_date_current_q 
    # [1] "2014-10-01"
    
    # last date in previous quarter
    last_date_prev_q <- first_date_current_q - 1
    last_date_prev_q
    # [1] "2014-09-30"
    

    And a short version by @G.Grothendieck (thanks!)

    as.Date(as.yearqtr(date)) - 1
    # [1] "2014-09-30"
    

    A nice base R solution by @G.Grothendieck

    as.Date(cut(date, "quarter")) - 1
    # [1] "2014-09-30"
    

    Another possibility is to use timeFirstDayInQuarter and timeLastDayInQuarter functions in package timeDate:

    library(timeDate)
    timeLastDayInQuarter(timeFirstDayInQuarter(date) - 1)
    # GMT
    # [1] [2014-09-30]