I have two dates expressed as datetime objects and trying to calculate the time between the two dates in fractions of years (equivalent to the Excel yearfrac function).
Using relativedelta I can get the number of years, number of months and number of days between the dates, but not the fraction of years, and I can also subtract the dates to get the number of days, but dividing by 365.25 doesn't seem to get me the answer I would expect.
start_date = dt.datetime(2010, 12, 31)
end_date = dt.datetime(2019, 5, 16);
delta = relativedelta(end_date, start_date);
print(delta)
This is the output I get:
relativedelta(years=+8, months=+4, days=+16)
What I am looking for is: 8.38
If I use the following code:
delta = (end_date - start_date)/365.25
print(delta)
I get output of: 8 days, 8:56:10.841889
I just did the math of 8 + ((months * 30) + days)/365 = 8.3726. This is assuming 30 days in all months and 365 days in a year. Less precise but can fit on one line. What do you get when you divide by the number 365.25 that makes it wrong? How precise does it have to be?
If you need absolute precision, I would simply do:
from datetime import date
d0 = date(2010, 12, 31)
d1 = date(2019, 5, 16)
delta = d1 - d0
delta_fraction = delta.days/365.25
print(delta_fraction)
# Output: 8.72348
EDIT This is a simplified solution assuming 365.25 days in a year (you can use 365.2425 days to be accurate up to the 400 year exception) to account for leap years. If you require it to match exactly excel's output, your probably better off writing a vba macro for excel
One thing to remember is that datetime.datetime objects have the subtraction operator defined, returning a datetime.timedelta object. And datetime.timedelta objects have the division operator defined, so you can get a ratio between a timedelta and either a common year (365 days) or the average length of all common and leap years (365 days, 5 hours, 49 minutes and 12 seconds).
import datetime as dt
start_date = dt.datetime(2010, 12, 31)
end_date = dt.datetime(2019, 5, 16)
print(round((end_date-start_date)/dt.timedelta(365,0,0,0),2)) #8.38
print(round((end_date-start_date)/dt.timedelta(365,5,49,12),2)) #8.38
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With