Python: get datetime for '3 years ago today'
PythonDatetimeTimedeltaPython 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)