Python: get datetime for '3 years ago today'

PythonDatetimeTimedelta

Python Problem Overview


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.

Python Solutions


Solution 1 - Python

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 2 - Python

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

Solution 3 - Python

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 - Python

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)

Solution 5 - Python

This works to cater for leap year corner cases and non-leap years too. Because, if day = 29 and month = 2 (Feb), a non-leap year would throw a value error because there is no 29th Feb and the last day of Feb would be 28th, thus doing a -1 on the date works in a try-except block.

from datetime import datetime

last_year = datetime.today().year - 1
month = datetime.today().month
day = datetime.today().day

try:
    # try returning same date last year
    last_year_date = datetime.strptime(f"{last_year}-{month}-{day}",'%Y-%m-%d').date()
except ValueError: 
    # incase of error due to leap year, return date - 1 in last year
    last_year_date = datetime.strptime(f"{last_year}-{month}-{day-1}",'%Y-%m-%d').date()

print(last_year_date)

Solution 6 - Python

In [3]: import datetime as dt

In [4]: today=dt.date.today()

In [5]: three_years_ago=today-dt.timedelta(days=3*365)

In [6]: three_years_ago
Out[6]: datetime.date(2008, 3, 1)

Solution 7 - Python

Why not simply do a check for leap year before replacing the year. This does not need any extra package or try:Except.

def years_ago(dt, years):
    if dt.month == 2 and dt.day == 29:
        dt = dt.replace(day=28)

    return dt.replace(year=dt.year - years)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAP257View Question on Stackoverflow
Solution 1 - PythonVince SpicerView Answer on Stackoverflow
Solution 2 - PythonFábio DinizView Answer on Stackoverflow
Solution 3 - PythonGlenn MaynardView Answer on Stackoverflow
Solution 4 - PythonMark RansomView Answer on Stackoverflow
Solution 5 - Pythonshilpa sindheView Answer on Stackoverflow
Solution 6 - PythonunutbuView Answer on Stackoverflow
Solution 7 - PythonmilkbreadView Answer on Stackoverflow