2

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

IronMarshal
  • 69
  • 1
  • 9
  • Possible duplicate of [Replicating YEARFRAC() function from Excel in Python](https://stackoverflow.com/questions/43355292/replicating-yearfrac-function-from-excel-in-python) – jose_bacoy May 17 '19 at 20:22

2 Answers2

4

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

Joe6.626070
  • 321
  • 1
  • 9
4

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
Matthew Cole
  • 602
  • 5
  • 21