0

In the code below, the first call to the EOMONTH function returns NA when I expect February 28, 2019. The second call works correctly. Both calls work correctly in Excel which this function is trying to replicate. Is this a bug or am I doing something wrong?

library(tidyquant)
sdt <- as.Date("2019-01-31")
EOMONTH(sdt, 1)
EOMONTH(sdt, 2)

I have version 1.0.4 of tidyquant and version 4.1.2 of R (Bird Hippie)

rmacey
  • 599
  • 3
  • 22
  • It is related to the assignment in the source code with `month` `lubridate::month(start_date) <- lubridate::month(start_date) + 1` where the month is changed to 2, but that date doesn't exist i.e. `EOMONTH(sdt, 3)# [1] NA` givves the same error because it is 30 day month – akrun Jun 12 '22 at 17:56

1 Answers1

2

Use a an earlier date, for example the first of the month, to avoid the trouble of getting a non-existing end-of-month date. The problem is related to date calculus and difference period 'plus one month' (implicitly getting the last of the month which may not exist when you start from the 31st) and 'plus 30 days'.

> EOMONTH(as.Date("2019-01-01"), 0:4)
[1] "2019-01-31" "2019-02-28" "2019-03-31" "2019-04-30" "2019-05-31"
> 

If you check help(EOMONTH) you will see similar usage in the provided examples.

Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
  • Here is code that should work even for the example I gave. It is based on the logic that the end of a month is one day before the end of the next month. EOMONTH2 <- function(start_date, months = 0){ if (rlang::is_missing(start_date)) start_date <- TODAY() start_date <- lubridate::as_date(start_date) y <- year(start_date) + floor(months / 12) months <- months - floor(months / 12) * 12 m <- month(start_date) + months if(m >= 11) y <- y + 1 m <- m + 1 if(m > 12) m <- m - 12 return(make_date(y, m, 1) - days(1)) } – rmacey Jun 12 '22 at 18:42
  • 1
    Sure. That is a known trick I also used in this ten-year old and widely-viewed answer (which uses no packages besides base R): https://stackoverflow.com/a/8334531/143305 But you brought `EOMONTH()` in so I was trying to show you how usage of it with a slightly different agument ca also work. – Dirk Eddelbuettel Jun 12 '22 at 19:19