I have a Python datetime.datetime
object. What is the best way to subtract one day?
7 Answers
You can use a timedelta
object:
from datetime import datetime, timedelta
d = datetime.today() - timedelta(days=days_to_subtract)
If your Python datetime object is timezone-aware than you should be careful to avoid errors around DST transitions (or changes in UTC offset for other reasons):
from datetime import datetime, timedelta
from tzlocal import get_localzone # pip install tzlocal
DAY = timedelta(1)
local_tz = get_localzone() # get local timezone
now = datetime.now(local_tz) # get timezone-aware datetime object
day_ago = local_tz.normalize(now - DAY) # exactly 24 hours ago, time may differ
naive = now.replace(tzinfo=None) - DAY # same time
yesterday = local_tz.localize(naive, is_dst=None) # but elapsed hours may differ
In general, day_ago
and yesterday
may differ if UTC offset for the local timezone has changed in the last day.
For example, daylight saving time/summer time ends on Sun 2-Nov-2014 at 02:00:00 A.M. in America/Los_Angeles timezone therefore if:
import pytz # pip install pytz
local_tz = pytz.timezone('America/Los_Angeles')
now = local_tz.localize(datetime(2014, 11, 2, 10), is_dst=None)
# 2014-11-02 10:00:00 PST-0800
then day_ago
and yesterday
differ:
day_ago
is exactly 24 hours ago (relative tonow
) but at 11 am, not at 10 am asnow
yesterday
is yesterday at 10 am but it is 25 hours ago (relative tonow
), not 24 hours.
pendulum
module handles it automatically:
>>> import pendulum # $ pip install pendulum
>>> now = pendulum.create(2014, 11, 2, 10, tz='America/Los_Angeles')
>>> day_ago = now.subtract(hours=24) # exactly 24 hours ago
>>> yesterday = now.subtract(days=1) # yesterday at 10 am but it is 25 hours ago
>>> (now - day_ago).in_hours()
24
>>> (now - yesterday).in_hours()
25
>>> now
<Pendulum [2014-11-02T10:00:00-08:00]>
>>> day_ago
<Pendulum [2014-11-01T11:00:00-07:00]>
>>> yesterday
<Pendulum [2014-11-01T10:00:00-07:00]>
Just to Elaborate an alternate method and a Use case for which it is helpful:
- Subtract 1 day from current datetime:
from datetime import datetime, timedelta print datetime.now() + timedelta(days=-1) # Here, I am adding a negative timedelta
- Useful in the Case, If you want to add 5 days and subtract 5 hours from current datetime. i.e. What is the Datetime 5 days from now but 5 hours less ?
from datetime import datetime, timedelta print datetime.now() + timedelta(days=5, hours=-5)
It can similarly be used with other parameters e.g. seconds, weeks etc
Also just another nice function i like to use when i want to compute i.e. first/last day of the last month or other relative timedeltas etc. ...
The relativedelta function from dateutil function (a powerful extension to the datetime lib)
import datetime as dt
from dateutil.relativedelta import relativedelta
#get first and last day of this and last month)
today = dt.date.today()
first_day_this_month = dt.date(day=1, month=today.month, year=today.year)
last_day_last_month = first_day_this_month - relativedelta(days=1)
print (first_day_this_month, last_day_last_month)
>2015-03-01 2015-02-28
class myDate:
def __init__(self):
self.day = 0
self.month = 0
self.year = 0
## for checking valid days month and year
while (True):
d = int(input("Enter The day :- "))
if (d > 31):
print("Plz 1 To 30 value Enter ........")
else:
self.day = d
break
while (True):
m = int(input("Enter The Month :- "))
if (m > 13):
print("Plz 1 To 12 value Enter ........")
else:
self.month = m
break
while (True):
y = int(input("Enter The Year :- "))
if (y > 9999 and y < 0000):
print("Plz 0000 To 9999 value Enter ........")
else:
self.year = y
break
## method for aday ands cnttract days
def adayDays(self, n):
## aday days to date day
nd = self.day + n
print(nd)
## check days subtract from date
if nd == 0: ## check if days are 7 subtracted from 7 then,........
if(self.year % 4 == 0):
if(self.month == 3):
self.day = 29
self.month -= 1
self.year = self. year
else:
if(self.month == 3):
self.day = 28
self.month -= 1
self.year = self. year
if (self.month == 5) or (self.month == 7) or (self.month == 8) or (self.month == 10) or (self.month == 12):
self.day = 30
self.month -= 1
self.year = self. year
elif (self.month == 2) or (self.month == 4) or (self.month == 6) or (self.month == 9) or (self.month == 11):
self.day = 31
self.month -= 1
self.year = self. year
elif(self.month == 1):
self.month = 12
self.year -= 1
## nd == 0 if condition over
## after subtract days to day io goes into negative then
elif nd < 0 :
n = abs(n)## return positive if no is negative
for i in range (n,0,-1): ##
if self.day == 0:
if self.month == 1:
self.day = 30
self.month = 12
self.year -= 1
else:
self.month -= 1
if(self.month == 1) or (self.month == 3)or (self.month == 5) or (self.month == 7) or (self.month == 8) or (self.month == 10) or (self.month ==12):
self.day = 30
elif(self.month == 4)or (self.month == 6) or (self.month == 9) or (self.month == 11):
self.day = 29
elif(self.month == 2):
if(self.year % 4 == 0):
self.day == 28
else:
self.day == 27
else:
self.day -= 1
## enf of elif negative days
## adaying days to DATE
else:
cnt = 0
while (True):
if self.month == 2: # check leap year
if(self.year % 4 == 0):
if(nd > 29):
cnt = nd - 29
nd = cnt
self.month += 1
else:
self.day = nd
break
## if not leap year then
else:
if(nd > 28):
cnt = nd - 28
nd = cnt
self.month += 1
else:
self.day = nd
break
## checking month other than february month
elif(self.month == 1) or (self.month == 3) or (self.month == 5) or (self.month == 7) or (self.month == 8) or (self.month == 10) or (self.month == 12):
if(nd > 31):
cnt = nd - 31
nd = cnt
if(self.month == 12):
self.month = 1
self.year += 1
else:
self.month += 1
else:
self.day = nd
break
elif(self.month == 4) or (self.month == 6) or (self.month == 9) or (self.month == 11):
if(nd > 30):
cnt = nd - 30
nd = cnt
self.month += 1
else:
self.day = nd
break
## end of month condition
## end of while loop
## end of else condition for adaying days
def formatDate(self,frmt):
if(frmt == 1):
ff=str(self.day)+"-"+str(self.month)+"-"+str(self.year)
elif(frmt == 2):
ff=str(self.month)+"-"+str(self.day)+"-"+str(self.year)
elif(frmt == 3):
ff =str(self.year),"-",str(self.month),"-",str(self.day)
elif(frmt == 0):
print("Thanky You.....................")
else:
print("Enter Correct Choice.......")
print(ff)
dt = myDate()
nday = int(input("Enter No. For Aday or SUBTRACT Days :: "))
dt.adayDays(nday)
print("1 : day-month-year")
print("2 : month-day-year")
print("3 : year-month-day")
print("0 : EXIT")
frmt = int (input("Enter Your Choice :: "))
dt.formatDate(frmt)
enter code here