Reputation: 1155
I am trying to define a customized function to get the difference in years between two dates,
Here's what I got so far:
library(lubridate)
## function to get the difference between years ##
set_dif_years <- function(end_date, start_date){
return(lubridate :: year(end_date)- lubridate :: year(start_date))
}
## testing function ##
set_dif_years(end_date=format(as.Date('01/08/2019', format='%d/%m/%Y'), "%d/%m/%Y"),
start_date=format(as.Date('28/08/2019', format='%d/%m/%Y'), "%d/%m/%Y"))
Console output:
# -27
For this case expected function output should be 0
.
However I can't figure out what is missing in the function,
Is there any way to adjust the function in order to get desired result?
Upvotes: 1
Views: 25
Reputation: 160407
When you get illogical results, look at all intermediate objects.
format(as.Date('01/08/2019', format='%d/%m/%Y'), "%d/%m/%Y")
# [1] "01/08/2019"
lubridate::year(format(as.Date('01/08/2019', format='%d/%m/%Y'), "%d/%m/%Y"))
# [1] 1
Does that make sense? Let's look at the other one.
format(as.Date('28/08/2019', format='%d/%m/%Y'), "%d/%m/%Y")
# [1] "28/08/2019"
lubridate::year(format(as.Date('28/08/2019', format='%d/%m/%Y'), "%d/%m/%Y"))
# [1] 28
This is because you lubridate::year
is using as.POSIXlt
, with no candidate date formats, which thinks that the first number is the year. (Don't confuse human-eyes-obvious with machine-obvious/unambiguous.)
as.POSIXlt(format(as.Date('01/08/2019', format='%d/%m/%Y'), "%d/%m/%Y"))
# [1] "0001-08-20 LMT"
as.POSIXlt(format(as.Date('28/08/2019', format='%d/%m/%Y'), "%d/%m/%Y"))
# [1] "0028-08-20 LMT"
Fixes:
don't go back and forth and back again between Date
and Class
; if you want to do year-arithmetic, just convert to the Date
class and stick with it
set_dif_years(end_date=as.Date('01/08/2019', format='%d/%m/%Y'),
start_date=as.Date('28/08/2019', format='%d/%m/%Y'))
if you must use character
, however, since year
does not accept format=
that most date/datetime functions allow, you need to make it an unambiguous string up-front:
set_dif_years(end_date=format(as.Date('01/08/2019', format='%d/%m/%Y'), "%Y/%m/%d"),
start_date=format(as.Date('28/08/2019', format='%d/%m/%Y'), "%Y/%m/%d"))
Upvotes: 2