Python timedelta in years

You need more than a timedelta to tell how many years have passed; you also need to know the beginning (or ending) date. (It's a leap year thing.)

Your best bet is to use the dateutil.relativedelta object, but that's a 3rd party module. If you want to know the datetime that was n years from some date (defaulting to right now), you can do the following::

from dateutil.relativedelta import relativedelta

def yearsago(years, from_date=None):
    if from_date is None:
        from_date = datetime.now()
    return from_date - relativedelta(years=years)

If you'd rather stick with the standard library, the answer is a little more complex::

from datetime import datetime
def yearsago(years, from_date=None):
    if from_date is None:
        from_date = datetime.now()
    try:
        return from_date.replace(year=from_date.year - years)
    except ValueError:
        # Must be 2/29!
        assert from_date.month == 2 and from_date.day == 29 # can be removed
        return from_date.replace(month=2, day=28,
                                 year=from_date.year-years)

If it's 2/29, and 18 years ago there was no 2/29, this function will return 2/28. If you'd rather return 3/1, just change the last return statement to read::

    return from_date.replace(month=3, day=1,
                             year=from_date.year-years)

Your question originally said you wanted to know how many years it's been since some date. Assuming you want an integer number of years, you can guess based on 365.25 days per year and then check using either of the yearsago functions defined above::

def num_years(begin, end=None):
    if end is None:
        end = datetime.now()
    num_years = int((end - begin).days / 365.25)
    if begin > yearsago(num_years, end):
        return num_years - 1
    else:
        return num_years

If you're trying to check if someone is 18 years of age, using timedelta will not work correctly on some edge cases because of leap years. For example, someone born on January 1, 2000, will turn 18 exactly 6575 days later on January 1, 2018 (5 leap years included), but someone born on January 1, 2001, will turn 18 exactly 6574 days later on January 1, 2019 (4 leap years included). Thus, you if someone is exactly 6574 days old, you can't determine if they are 17 or 18 without knowing a little more information about their birthdate.

The correct way to do this is to calculate the age directly from the dates, by subtracting the two years, and then subtracting one if the current month/day precedes the birth month/day.


First off, at the most detailed level, the problem can't be solved exactly. Years vary in length, and there isn't a clear "right choice" for year length.

That said, get the difference in whatever units are "natural" (probably seconds) and divide by the ratio between that and years. E.g.

delta_in_days / (365.25)
delta_in_seconds / (365.25*24*60*60)

...or whatever. Stay away from months, since they are even less well defined than years.