R subtracting 1 month from today's date gives NA

Amy M picture Amy M · Mar 29, 2017 · Viewed 8.4k times · Source

I have a script in which I subset my data according to some set time periods and wanted to subset all the records that had occurred in the last month.

However if I try to subtract one month from today's date it yields an NA:

> today <- Sys.Date()
> today
[1] "2017-03-29"
> today - months(1)
[1] NA

I do have lubridate loaded but I think this calculation is being performed with base R. If I subtract 2 or more months it works fine:

> today - months(2)
[1] "2017-01-29"
> today - months(3)
[1] "2016-12-29"

Does anyone have any ideas about what might be going on?

UPDATE: I think this is something to do with simple date subtraction not handling leap year cases (2017 is not a leap year so "2017-02-29" does not exist).

Are there other packages / functions that take into account leap years? For the above example I would expect the answer to revert to the last day of the previous month, i.e.:

today - months(1)
# Should yield:
"2017-02-28"

Would it make sense for this calculation to give the same results for both today and yesterday (or what is the ISO convention for this)?

> sessionInfo()
R version 3.3.2 (2016-10-31)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 7 x64 (build 7601) Service Pack 1

locale:
[1] LC_COLLATE=English_United Kingdom.1252  LC_CTYPE=English_United Kingdom.1252   
[3] LC_MONETARY=English_United Kingdom.1252 LC_NUMERIC=C                           
[5] LC_TIME=English_United Kingdom.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] xlsx_0.5.7         xlsxjars_0.6.1     rJava_0.9-8        MRAtools_0.6.8     stringdist_0.9.4.4 stringr_1.2.0     
 [7] stringi_1.1.3      lubridate_1.6.0    data.table_1.10.4  PKI_0.1-3          base64enc_0.1-3    digest_0.6.12     
[13] getPass_0.1-1      RPostgreSQL_0.5-1  DBI_0.5-1         

loaded via a namespace (and not attached):
[1] magrittr_1.5   rstudioapi_0.6 tools_3.3.2    parallel_3.3.2

Answer

Pierre Lapointe picture Pierre Lapointe · Mar 29, 2017

The calculation of months is indeed perfomed by base R but not the way your think. Months is used to get the month of a date object.

#Example
today <- Sys.Date()
months(today)
[1] "March"

To add or substract months, you should use %m+% from lubridate:

today <- Sys.Date()
today %m+% months(-1)
[1] "2017-02-28"