0

I have multiple relativedelta values in Python 3 and I would like to take an average of all these. For example, for the 2 values below, I would like a relativedelta value where hours = +3 day (average between the two).

relativedelta(days=+2, hours=+1, minutes=+33, seconds=+51)
relativedelta(hours=+4, minutes=+35, seconds=+36)

How can I calculate the average between a list? If there was a way to get the total number of hours for each value, I could add them up and divide by number of values, then divide by 24 to get days?

Brad Solomon
  • 38,521
  • 31
  • 149
  • 235
Peter
  • 427
  • 2
  • 7
  • 22

1 Answers1

0

There's no way to do this directly within dateutil. You could instead anchor both to a datetime and find a timedelta between the anchored dates. The number below is expressed in days, stemming from the fact that there are 86,400 seconds in a day:

from dateutil.relativedelta import relativedelta
from datetime import datetime      
from statistics import mean

def avg_relativedelta(*relativedeltas):
    dates = (anchor - rd for rd in relativedeltas)
    tds = (anchor - date for date in dates)
    return mean(td.total_seconds() for td in tds) / 86400

i1 = relativedelta(days=2, hours=1, minutes=33, seconds=51)
i2 = relativedelta(hours=4, minutes=35, seconds=36)
i3 = relativedelta(days=6, minutes=10)

avg_relativedelta(i1, i2, i3)
# 2.7545023148148147

avg_relativedelta(i1, i2)
# 1.12828125

It's a bit unintuitive that you'd need to subtract the relativedelta from a datetime, then subtract this datetime from the same datetime. But basically this is a means of converting relativedelta to timedelta, the later of which is able to aggregate up its units.

Alternatively:

def total_days_in_relativedelta(reldelta):
    total_days = reldelta.years * 365 \
               + reldelta.months * 12 \
               + reldelta.weeks * 52 \
               + reldelta.days \
               + reldelta.minutes * 1440 \
               + reldelta.seconds * 86400 \
               + reldelta.microseconds * 1000000
    return total_days


def avg_relativedelta(*relativedeltas):
    return mean(total_days_in_relativedelta(rd) for rd in relativedeltas)
Brad Solomon
  • 38,521
  • 31
  • 149
  • 235