Python: get datetime for '3 years ago today'

83,124

Solution 1

import datetime
datetime.datetime.now() - datetime.timedelta(days=3*365)

Solution 2

If you need to be exact use the dateutil module to calculate relative dates

from datetime import datetime
from dateutil.relativedelta import relativedelta

three_yrs_ago = datetime.now() - relativedelta(years=3)

Solution 3

Subtracting 365*3 days is wrong, of course--you're crossing a leap year more than half the time.

dt = datetime.now()
dt = dt.replace(year=dt.year-3)
# datetime.datetime(2008, 3, 1, 13, 2, 36, 274276)

ED: To get the leap-year issue right,

def subtract_years(dt, years):
    try:
        dt = dt.replace(year=dt.year-years)
    except ValueError:
        dt = dt.replace(year=dt.year-years, day=dt.day-1)
    return dt

Solution 4

def add_years(dt, years):
    try:
        result = datetime.datetime(dt.year + years, dt.month, dt.day, dt.hour, dt.minute, dt.second, dt.microsecond, dt.tzinfo)
    except ValueError:
        result = datetime.datetime(dt.year + years, dt.month, dt.day - 1, dt.hour, dt.minute, dt.second, dt.microsecond, dt.tzinfo)
    return result

>>> add_years(datetime.datetime.now(), -3)
datetime.datetime(2008, 3, 1, 12, 2, 35, 22000)
>>> add_years(datetime.datetime(2008, 2, 29), -3)
datetime.datetime(2005, 2, 28, 0, 0)
Share:
83,124

Related videos on Youtube

AP257
Author by

AP257

Updated on January 20, 2022

Comments

  • AP257
    AP257 over 2 years

    In Python, how do I get a datetime object for '3 years ago today'?

    UPDATE: FWIW, I don't care hugely about accuracy... i.e. it's Feb 29th today, I don't care whether I'm given Feb 28th or March 1st in my answer. Concision is more important than configurability, in this case.

    • Mark Ransom
      Mark Ransom about 13 years
      Presumably if it's March 1 today, you want to get March 1 no matter if a leap year occurs in between or not? I think all the existing answers fail in that regard.
    • Glenn Maynard
      Glenn Maynard about 13 years
      This site really needs a way for the community to override when people accept a clearly incorrect answer. 3*365 days is not 3 years, and there's a correct answer right there.
  • Jochen Ritzel
    Jochen Ritzel about 13 years
    Well, now you have that other issue: datetime.datetime(2008,2,29).replace(year=2005) -> ValueError. It is still more accurate to catch that error and just subtract one extra day I guess.
  • Mark Ransom
    Mark Ransom about 13 years
    I keep forgetting about replace. It makes for a simpler solution than mine.
  • Glenn Maynard
    Glenn Maynard about 13 years
    @Mark: I did at first, too; I initially did what you did. The site seems to have misplaced that version in the edit history, though.
  • PartialOrder
    PartialOrder over 10 years
    What happens after 2100?