Add month to date

I am trying to add a month to the date that I have. But then this is not possible in direct form. Here is what I have tried.

d <- as.Date("2004-01-31") d + 60 # [1] "2004-03-31" 

Adding wont help as the month will not overlap.

 seq(as.Date("2004-01-31"), by = "month", length = 2) # [1] "2004-01-31" "2004-03-02" 

The above may work, but again this is not straightforward. In addition, it also adds 30 days or something else to a date that has issues such as below

 seq(as.Date("2004-01-31"), by = "month", length = 10) # [1] "2004-01-31" "2004-03-02" "2004-03-31" "2004-05-01" "2004-05-31" "2004-07-01" "2004-07-31" "2004-08-31" "2004-10-01" "2004-10-31" 

In the above example, for the first two dates, havent month changed.

Also, the following approach also failed for a month, but was successful for a year

 d <- as.POSIXlt(as.Date("2010-01-01")) d$year <- d$year +1 d # [1] "2011-01-01 UTC" d <- as.POSIXlt(as.Date("2010-01-01")) d$month <- d$month +1 d 

Error in format.POSIXlt(x, usetz = TRUE) : invalid argument "x"

What is the right way to do this?

+44
date r date-arithmetic
Jan 05 '13 at 7:20
source share
8 answers

Vanilla R has a naive difftime class, but Lubridate CRAN allows you to do what you ask for:

 require(lubridate) d <- as.Date('2004-01-01') month(d) <- month(d) + 1 day(d) <- days_in_month(d) d [1] "2004-02-29" 

Hope this helps.

+21
Jan 05 '13 at 7:38
source share

The %m+% of lubridate function adds one month without exceeding the 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" 
+77
Jan 06 '13 at
source share

This is mixed when you say "add a month to a date."

You mean

  • add 30 days?
  • increase the month of the date by 1?

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

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

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

As for the second, I would just create one line as easy as (and with a more general area):

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

You can use it with arbitrary months, including negative ones:

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

Of course, if you want to add only often one month:

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

If you add one month before January 31, from February 31 it makes no sense, it is best to complete the task - add the missing 3 days in the next month, in March. So right:

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

If for some special reason you need to install the ceiling on the last available day of the month, this is a little 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 can add a one-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" 

In addition, you did not indicate whether you were interested in a scalar or vector solution. Regarding 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, so it needs to be rebuilt. In the vector version:

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

I hope you enjoyed it))

+39
Mar 09 '13 at 23:29
source share

"mondate" somewhat similar to "Date" , except that adding n adds n months, not n days:

 > library(mondate) > d <- as.Date("2004-01-31") > as.mondate(d) + 1 mondate: timeunits="months" [1] 2004-02-29 
+7
Mar 10 '13 at 1:37
source share

Here is a function that does not require the installation of any packages. You give it a Date object (or character , which it can convert to Date ), and it adds n months to that date without changing the day of the month (if there aren’t enough days for the month you landed on, in which case defaults to the last day of the returned month). Just in case, it does not make sense to read it, there are several examples below.

Function Definition

 addMonth <- function(date, n = 1){ if (n == 0){return(date)} if (n %% 1 != 0){stop("Input Error: argument 'n' must be an integer.")} # Check to make sure we have a standard Date format if (class(date) == "character"){date = as.Date(date)} # Turn the year, month, and day into numbers so we can play with them y = as.numeric(substr(as.character(date),1,4)) m = as.numeric(substr(as.character(date),6,7)) d = as.numeric(substr(as.character(date),9,10)) # Run through the computation i = 0 # Adding months if (n > 0){ while (i < n){ m = m + 1 if (m == 13){ m = 1 y = y + 1 } i = i + 1 } } # Subtracting months else if (n < 0){ while (i > n){ m = m - 1 if (m == 0){ m = 12 y = y - 1 } i = i - 1 } } # If past 28th day in base month, make adjustments for February if (d > 28 & m == 2){ # If it a leap year, return the 29th day if ((y %% 4 == 0 & y %% 100 != 0) | y %% 400 == 0){d = 29} # Otherwise, return the 28th day else{d = 28} } # If 31st day in base month but only 30 days in end month, return 30th day else if (d == 31){if (m %in% c(1, 3, 5, 7, 8, 10, 12) == FALSE){d = 30}} # Turn year, month, and day into strings and put them together to make a Date y = as.character(y) # If month is single digit, add a leading 0, otherwise leave it alone if (m < 10){m = paste('0', as.character(m), sep = '')} else{m = as.character(m)} # If day is single digit, add a leading 0, otherwise leave it alone if (d < 10){d = paste('0', as.character(d), sep = '')} else{d = as.character(d)} # Put them together and convert return the result as a Date return(as.Date(paste(y,'-',m,'-',d, sep = ''))) } 

Some examples

Adding months

 > addMonth('2014-01-31', n = 1) [1] "2014-02-28" # February, non-leap year > addMonth('2014-01-31', n = 5) [1] "2014-06-30" # June only has 30 days, so day of month dropped to 30 > addMonth('2014-01-31', n = 24) [1] "2016-01-31" # Increments years when n is a multiple of 12 > addMonth('2014-01-31', n = 25) [1] "2016-02-29" # February, leap year 

Subtraction of months

 > addMonth('2014-01-31', n = -1) [1] "2013-12-31" > addMonth('2014-01-31', n = -7) [1] "2013-06-30" > addMonth('2014-01-31', n = -12) [1] "2013-01-31" > addMonth('2014-01-31', n = -23) [1] "2012-02-29" 
+4
Jul 29 '14 at 22:06
source share
 addedMonth <- seq(as.Date('2004-01-01'), length=2, by='1 month')[2] addedQuarter <- seq(as.Date('2004-01-01'), length=2, by='1 quarter')[2] 
+2
Jun 22 '17 at 4:34 on
source share

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

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

Also, if you want to deal with Date columns in data.table, unfortunately, the POSIXlt format is not supported.

However, you can complete the month of adding 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 this helps.

+2
Aug 29 '17 at 3:36 on
source share

I turned antonio thoughts into a specific function:

 library(DescTools) > AddMonths(as.Date('2004-01-01'), 1) [1] "2004-02-01" > AddMonths(as.Date('2004-01-31'), 1) [1] "2004-02-29" > AddMonths(as.Date('2004-03-30'), -1) [1] "2004-02-29" 
0
Apr 29 '15 at
source share



All Articles