Add a month to a Date

Vanilla R has a naive difftime class, but the Lubridate CRAN package lets you do what you ask:

require(lubridate)
d <- ymd(as.Date('2004-01-01')) %m+% months(1)
d
[1] "2004-02-01"

Hope that helps.


The simplest way is to convert Date to POSIXlt format. Then perform the arithmetic operation as follows:

date_1m_fwd     <- as.POSIXlt("2010-01-01")
date_1m_fwd$mon <- date_1m_fwd$mon +1

Moreover, incase you want to deal with Date columns in data.table, unfortunately, POSIXlt format is not supported.

Still you can perform the add month using basic R codes as follows:

library(data.table)  
dt <- as.data.table(seq(as.Date("2010-01-01"), length.out=5, by="month"))  
dt[,shifted_month:=tail(seq(V1[1], length.out=length(V1)+3, by="month"),length(V1))]

Hope it helps.


It is ambiguous when you say "add a month to a date".

Do you mean

  1. add 30 days?
  2. increase the month part of the date by 1?

In both cases a whole package for a simple addition seems a bit exaggerated.

For the first point, of course, the simple + operator will do:

d=as.Date('2010-01-01') 
d + 30 
#[1] "2010-01-31"

As for the second I would just create a one line function as simple as that (and with a more general scope):

add.months= function(date,n) seq(date, by = paste (n, "months"), length = 2)[2]

You can use it with arbitrary months, including negative:

add.months(d, 3)
#[1] "2010-04-01"
add.months(d, -3)
#[1] "2009-10-01"

Of course, if you want to add only and often a single month:

add.month=function(date) add.months(date,1)
add.month(d)
#[1] "2010-02-01"

If you add one month to 31 of January, since 31th February is meaningless, the best to get the job done is to add the missing 3 days to the following month, March. So correctly:

add.month(as.Date("2010-01-31"))
#[1] "2010-03-03"

In case, for some very special reason, you need to put a ceiling to the last available day of the month, it's a bit longer:

add.months.ceil=function (date, n){

  #no ceiling
  nC=add.months(date, n)

  #ceiling
  day(date)=01
  C=add.months(date, n+1)-1

  #use ceiling in case of overlapping
  if(nC>C) return(C)
  return(nC)
}

As usual you could add a single month version:

add.month.ceil=function(date) add.months.ceil(date,1)    

So:

  d=as.Date('2010-01-31')
  add.month.ceil(d)
  #[1] "2010-02-28"
  d=as.Date('2010-01-21')
  add.month.ceil(d)
  #[1] "2010-02-21"

And with decrements:

  d=as.Date('2010-03-31')
  add.months.ceil(d, -1)
  #[1] "2010-02-28"
  d=as.Date('2010-03-21')
  add.months.ceil(d, -1)
  #[1] "2010-02-21"

Besides you didn't tell if you were interested to a scalar or vector solution. As for the latter:

add.months.v= function(date,n) as.Date(sapply(date, add.months, n), origin="1970-01-01")

Note: *apply family destroys the class data, that's why it has to be rebuilt. The vector version brings:

d=c(as.Date('2010/01/01'), as.Date('2010/01/31'))
add.months.v(d,1)
[1] "2010-02-01" "2010-03-03"

Hope you liked it))


Function %m+% from lubridate adds one month without exceeding last day of the new month.

library(lubridate)
(d <- ymd("2012-01-31"))
 1 parsed with %Y-%m-%d
[1] "2012-01-31 UTC"
d %m+% months(1)
[1] "2012-02-29 UTC"