I am looking to add and subtract six months reliably with lubridate
.
For example, adding six months to 12/31/2014
should result in 6/30/2015
,
and adding to 2/28/2014
should result in 8/31/2014
The issue with as.Date("2014-12-31") + months(6)
, is that it yields an NA
. Alternatively, the second result is 8/28/2014 because it doesn't just add 6 months to the month and then know where the day should end up dependent upon the month.
Is there any way to quickly correct this? At the moment, I am building a function to basically use a switch and consider each month, but this is very long and I am having problems with it as well.
Thanks!
The lubridate
function %m+%
may be useful here:
Add and subtract months to a date without exceeding the last day of the new month
as.Date("2014-12-31") %m+% months(6)
# [1] "2015-06-30"
To also handle the second case, you will need to round up to nearest month using ceiling_date
, and subtract one day using days
.
ceiling_date(as.Date("2014-02-28") %m+% months(6), unit = "month") - days(1)
# [1] "2014-08-31"
I just coded this out quickly, but I think it should work. I'm not sure if it's the most elegant solution, however.
# up = 1, down = -1
six.mo.mover<-function(date,up.or.down) {
last.day <- month(date) != month(as.Date(date)+1)
if(last.day) {
adj.date <- as.Date(date) - day(as.Date(date)-1) + up.or.down*months(6)
adj.mo <- month(adj.date)
if (adj.mo == 2) {
dy <- 28 + leap_year(year(adj.date))
}
else {
dy <- 31-(adj.mo-1)%%7%%2
}
adj.date + days(dy-1)
}
else {
as.Date(date)+up.or.down*months(6)
}
}
NB: not debugged, so check it yourself and let me know.