The difftime()
function makes it easy to compute the difference between two dates in days or in weeks but there is no option to compute the difference in months or in years. Is there any reason for that ? Would you know any function which would perform this task ?

- 5,178
- 8
- 38
- 62
-
Can you explain 'difference in months'? – TheComeOnMan Oct 30 '13 at 15:46
-
1The problem is that neither months nor years have a fixed length. – Roland Oct 30 '13 at 15:47
-
6months and years aren't precise time units, that is, their lengths vary. If you want to fix a value for them, e.g., month = 30 days, year = 365 days, you can just divide your difference in days to get the units you want. Or you just want the number complete months between two dates, ` length(seq(from=date1, to=date2, by='month')) - 1` – Matthew Plourde Oct 30 '13 at 15:50
-
1See also http://stackoverflow.com/questions/14454476/in-r-get-the-difference-between-dates-in-terms-of-weeks-months-quarters-years – plannapus Oct 30 '13 at 18:37
2 Answers
From the comments: Months and years aren't precise time units, that is, their lengths vary (months can have 28, 29, 30, 31 days. Years can have 365 or 366). If you want to fix a value for one of these units (e.g., month = 30 days, year = 365 days), you can just divide your difftime
s in days by the fixed value to get the difference in the units you want. Or if you just want something like the number of complete months between two dates, you could do this
date1 = as.Date('2012-1-2')
date2 = as.Date('2012-7-5')
length(seq(from=date1, to=date2, by='month')) - 1
# [1] 6
or for weeks:
length(seq(from=date1, to=date2, by='week')) - 1
# [1] 26

- 43,932
- 7
- 96
- 113
The POSIXlt
datetime-class is a list with several extraction methods including months
and quarter
. (The months
function returns a character value so you need to extract the mon
item from the list which is an integer.) If you want to subtract the months values from successive items in a vector it would be something along the lines of:
PLvec <- as.POSIXlt(vec)
PLvec[-1]$mon - PLvec[-length(PLvec)]$mon
vec <- seq(from = as.Date('2012-1-2'),
to = as.Date('2012-7-5'),
by="60 days")
PLvec <- as.POSIXlt(vec)
PLvec[-1]$mon - PLvec[-length(PLvec)]$mon
#[1] 2 2 1
You should educate yourself about POSIXlt classed items, because they are really lists and do not play well with data.frame storage.
dput(as.POSIXlt(Sys.time()))
structure(list(sec = 24.0051879882812, min = 5L, hour = 9L, mday = 30L,
mon = 9L, year = 113L, wday = 3L, yday = 302L, isdst = 1L), .Names = c("sec",
"min", "hour", "mday", "mon", "year", "wday", "yday", "isdst"
), class = c("POSIXlt", "POSIXt"), tzone = c("", "PST", "PDT"
))

- 258,963
- 21
- 364
- 487
-
If you wrap the code in a function you can keep the data.frame column as `POSIXct`. I try to avoid storing `POSIXlt` data. – Roland Oct 30 '13 at 16:16
-
I only use POSIXlt for output. I advised not using with data.frame storage. – IRTFM Oct 30 '13 at 16:17