888

I have a Python datetime.datetime object. What is the best way to subtract one day?

martineau
  • 99,260
  • 22
  • 139
  • 249
defrex
  • 13,028
  • 7
  • 32
  • 44
  • related: [Find if 24 hrs have passed between datetimes - Python](http://stackoverflow.com/q/26313520/4279) – jfs Feb 02 '15 at 12:52
  • This thread is directly useful to convert a day of the year to a date. – Hari Nov 09 '20 at 15:58

6 Answers6

1529

You can use a timedelta object:

from datetime import datetime, timedelta
    
d = datetime.today() - timedelta(days=days_to_subtract)
Boris
  • 7,044
  • 6
  • 62
  • 63
Steve B.
  • 49,740
  • 11
  • 90
  • 128
  • 21
    if you don't ignore timezones then [the answer is more complex](http://stackoverflow.com/a/25427822/4279). – jfs Aug 21 '14 at 13:39
  • 1
    Also, how do you relate it with a specific date. See my question: http://stackoverflow.com/questions/43092508/first-available-date-previous-day-month-year – JohnAndrews Mar 29 '17 at 12:10
  • It works with other units as well, I've used it with `timedelta(minutes=12)` for example. – Nagev Feb 16 '18 at 17:29
  • the documentation says that will return _"A duration expressing the difference between two date, time, or datetime instances..."._ how do you get the actual date of, say, 5 days ago or 5 days from now? – oldboy Jul 20 '18 at 03:34
89

Subtract datetime.timedelta(days=1)

S.Lott
  • 359,791
  • 75
  • 487
  • 757
72

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 to now) but at 11 am, not at 10 am as now
  • yesterday is yesterday at 10 am but it is 25 hours ago (relative to now), 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]>
jfs
  • 346,887
  • 152
  • 868
  • 1,518
44

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

Sahil kalra
  • 6,598
  • 3
  • 21
  • 29
9

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
PlagTag
  • 4,445
  • 2
  • 26
  • 42
7

Genial arrow module exists

import arrow
utc = arrow.utcnow()
utc_yesterday = utc.shift(days=-1)
print(utc, '\n', utc_yesterday)

output:

2017-04-06T11:17:34.431397+00:00 
 2017-04-05T11:17:34.431397+00:00
gr4viton
  • 99
  • 1
  • 2