3

I have two dates in R, and I want to create a vector of the dates in between them spaced at one-month intervals. However, R seems to be using 31-day intervals instead (sometimes?). For example:

x <- as.Date("31-01-1900", "%d-%m-%Y")
y <- as.Date("31-01-1901", "%d-%m-%Y")
seq(x, y, by="month")

 [1] "1900-01-31" "1900-03-03" "1900-03-31" "1900-05-01" "1900-05-31"
 [6] "1900-07-01" "1900-07-31" "1900-08-31" "1900-10-01" "1900-10-31"
[11] "1900-12-01" "1900-12-31" "1901-01-31"

What I wanted was a vector of dates, each of which is the final day in each month, like this:

 [1] "1900-01-31" "1900-02-29" "1900-03-31" "1900-04-30" "1900-05-31"
 [6] "1900-06-30" "1900-07-31" "1900-08-31" "1900-09-30" "1900-10-31"
[11] "1900-11-30" "1900-12-31" "1901-01-31"

Does R know the lengths of the months, or do I have to do it by hand?

Flounderer
  • 640
  • 5
  • 17
  • 2
    You may take a look at the `lubridate` package, however this is an excerpt from ?seq.POSIXt: "Using "month" first advances the month without changing the day: if this results in an invalid day of the month, it is counted forward into the next month." So it looks like this is fixed in these functions. – lmo Jun 22 '16 at 22:29

2 Answers2

5

We can use lubridate

library(lubridate)
x <- as.Date("31-01-1900", "%d-%m-%Y")
y <- as.Date("31-01-1901", "%d-%m-%Y")
c(x, x %m+% months(1:11), y)

[1] "1900-01-31" "1900-02-28" "1900-03-31" "1900-04-30"
[5] "1900-05-31" "1900-06-30" "1900-07-31" "1900-08-31"
[9] "1900-09-30" "1900-10-31" "1900-11-30" "1900-12-31"
[13] "1901-01-31"

Or, equivalently, and probably a little easier to read:

lubridate::add_with_rollback(x, months(0:12))

 [1] "1900-01-31" "1900-02-28" "1900-03-31" "1900-04-30"
 [5] "1900-05-31" "1900-06-30" "1900-07-31" "1900-08-31"
 [9] "1900-09-30" "1900-10-31" "1900-11-30" "1900-12-31"
[13] "1901-01-31"
bouncyball
  • 10,631
  • 19
  • 31
5

You can generate a sequence of the first of each month, then subtract 1

seq(as.Date("1900-02-01"), length = 12, by="1 month") - 1
# [1] "1900-01-31" "1900-02-28" "1900-03-31" "1900-04-30" "1900-05-31" "1900-06-30"
# [7] "1900-07-31" "1900-08-31" "1900-09-30" "1900-10-31" "1900-11-30" "1900-12-31"

## the same can be achieved with `seq.Date()`
# seq.Date(as.Date("1900-02-01"), by = "1 month", length.out = 12) - 1 
SymbolixAU
  • 25,502
  • 4
  • 67
  • 139