This is happening because of the 5 leap days between 1999 and 2018. Years can have two different lengths when denominated in days. I suppose the options depend on your use case. The code below returns the exact number of years, but won't give correct fractional years if the two dates are not on the same day of the year.
d2 = as_date("2018-09-18")
d1 = as_date("1999-09-18")
year(d2) - year(d1)
[1] 19
nleap = sum(leap_year(year(d1):year(d2)))
time_length(d2 - d1 - nleap, "years")
[1] 19
Would keeping track of year difference and the difference in day of the year for each date give you what you need? For example:
d3 = as_date("2018-08-20")
d4 = as_date("2018-10-09")
year_diff = function(date2, date1) {
year(date2) - year(date1) + (yday(date2) - yday(date1))/365
}
year_diff(d2, d1)
[1] 19
year_diff(d3, d1)
[1] 18.92055
year_diff(d4, d1)
[1] 19.05753
But note that this fails to return an integer year difference if one of the dates (but not both) is in a leap year and after February 28.
d5 = as_date("2020-09-18")
year_diff(d5, d1)
[1] 21.00274
And in general this method will differ by 1/365 when one date is in a leap year and after February 28 and the other is not in a leap year or is in a leap year but on or before February 28 (relative to the case where these issues don't occur). For example, in the code below we want both examples to return a difference of one year, but the second one doesn't because of the leap year issue.
d6 = as_date("2020-02-28")
d7 = as_date("2019-02-28")
d8 = as_date("2020-03-01")
d9 = as_date("2019-03-01")
year_diff(d6, d7)
[1] 1
year_diff(d8, d9)
[1] 1.00274
round(1/365, 5)
[1] 0.00274
Here's some additional logic to check for a leap-year mismatch between the two dates. Keep in mind that in all of these approaches we're removing leap days, so we're not calculating the actual elapsed time between two dates. Instead, we're calculating the elapsed time minus the number of leap days between the two dates.
year_diff = function(date2, date1) {
leap = sum(c(leap_year(date2) & yday(date2) > yday("2018-02-28"),
leap_year(date1) & yday(date1) > yday("2018-02-28"))) == 1
year(date2) - year(date1) + (yday(date2) - yday(date1) - ifelse(leap, 1, 0))/365
}
year_diff(d5, d1)
[1] 21
year_diff(d8, d9)
[1] 1