246

How to increment the day of a datetime?

for i in range(1, 35)
    date = datetime.datetime(2003, 8, i)
    print(date)

But I need pass through months and years correctly? Any ideas?

wim
  • 338,267
  • 99
  • 616
  • 750
Pol
  • 24,517
  • 28
  • 74
  • 95

8 Answers8

386
date = datetime.datetime(2003,8,1,12,4,5)
for i in range(5): 
    date += datetime.timedelta(days=1)
    print(date) 
unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
  • 12
    If you need to take into account daylight saving time; it is more complex e.g., see [How can I subtract a day from a python date?](http://stackoverflow.com/a/25427822/4279) – jfs Jun 25 '15 at 19:51
88

Incrementing dates can be accomplished using timedelta objects:

import datetime

datetime.datetime.now() + datetime.timedelta(days=1)

Look up timedelta objects in the Python docs: http://docs.python.org/library/datetime.html

Jon Hadley
  • 5,196
  • 8
  • 41
  • 65
Piotr Duda
  • 1,767
  • 11
  • 12
15

All of the current answers are wrong in some cases as they do not consider that timezones change their offset relative to UTC. So in some cases adding 24h is different from adding a calendar day.

Proposed solution

The following solution works for Samoa and keeps the local time constant.

def add_day(today):
    """
    Add a day to the current day.

    This takes care of historic offset changes and DST.

    Parameters
    ----------
    today : timezone-aware datetime object

    Returns
    -------
    tomorrow : timezone-aware datetime object
    """
    today_utc = today.astimezone(datetime.timezone.utc)
    tz = today.tzinfo
    tomorrow_utc = today_utc + datetime.timedelta(days=1)
    tomorrow_utc_tz = tomorrow_utc.astimezone(tz)
    tomorrow_utc_tz = tomorrow_utc_tz.replace(hour=today.hour,
                                              minute=today.minute,
                                              second=today.second)
    return tomorrow_utc_tz

Tested Code

# core modules
import datetime

# 3rd party modules
import pytz


# add_day methods
def add_day(today):
    """
    Add a day to the current day.

    This takes care of historic offset changes and DST.

    Parameters
    ----------
    today : timezone-aware datetime object

    Returns
    -------
    tomorrow : timezone-aware datetime object
    """
    today_utc = today.astimezone(datetime.timezone.utc)
    tz = today.tzinfo
    tomorrow_utc = today_utc + datetime.timedelta(days=1)
    tomorrow_utc_tz = tomorrow_utc.astimezone(tz)
    tomorrow_utc_tz = tomorrow_utc_tz.replace(hour=today.hour,
                                              minute=today.minute,
                                              second=today.second)
    return tomorrow_utc_tz


def add_day_datetime_timedelta_conversion(today):
    # Correct for Samoa, but dst shift
    today_utc = today.astimezone(datetime.timezone.utc)
    tz = today.tzinfo
    tomorrow_utc = today_utc + datetime.timedelta(days=1)
    tomorrow_utc_tz = tomorrow_utc.astimezone(tz)
    return tomorrow_utc_tz


def add_day_dateutil_relativedelta(today):
    # WRONG!
    from dateutil.relativedelta import relativedelta
    return today + relativedelta(days=1)


def add_day_datetime_timedelta(today):
    # WRONG!
    return today + datetime.timedelta(days=1)


# Test cases
def test_samoa(add_day):
    """
    Test if add_day properly increases the calendar day for Samoa.

    Due to economic considerations, Samoa went from 2011-12-30 10:00-11:00
    to 2011-12-30 10:00+13:00. Hence the country skipped 2011-12-30 in its
    local time.

    See https://stackoverflow.com/q/52084423/562769

    A common wrong result here is 2011-12-30T23:59:00-10:00. This date never
    happened in Samoa.
    """
    tz = pytz.timezone('Pacific/Apia')
    today_utc = datetime.datetime(2011, 12, 30, 9, 59,
                                  tzinfo=datetime.timezone.utc)
    today_tz = today_utc.astimezone(tz)  # 2011-12-29T23:59:00-10:00
    tomorrow = add_day(today_tz)
    return tomorrow.isoformat() == '2011-12-31T23:59:00+14:00'


def test_dst(add_day):
    """Test if add_day properly increases the calendar day if DST happens."""
    tz = pytz.timezone('Europe/Berlin')
    today_utc = datetime.datetime(2018, 3, 25, 0, 59,
                                  tzinfo=datetime.timezone.utc)
    today_tz = today_utc.astimezone(tz)  # 2018-03-25T01:59:00+01:00
    tomorrow = add_day(today_tz)
    return tomorrow.isoformat() == '2018-03-26T01:59:00+02:00'


to_test = [(add_day_dateutil_relativedelta, 'relativedelta'),
           (add_day_datetime_timedelta, 'timedelta'),
           (add_day_datetime_timedelta_conversion, 'timedelta+conversion'),
           (add_day, 'timedelta+conversion+dst')]
print('{:<25}: {:>5} {:>5}'.format('Method', 'Samoa', 'DST'))
for method, name in to_test:
    print('{:<25}: {:>5} {:>5}'
          .format(name,
                  test_samoa(method),
                  test_dst(method)))

Test results

Method                   : Samoa   DST
relativedelta            :     0     0
timedelta                :     0     0
timedelta+conversion     :     1     0
timedelta+conversion+dst :     1     1
Martin Thoma
  • 124,992
  • 159
  • 614
  • 958
  • 5
    The others answers are not entirely wrong, they are perfectly fine while working with UTC or naive (`tzinfo == None`) datetimes. – Delgan Nov 10 '18 at 19:08
14

Here is another method to add days on date using dateutil's relativedelta.

from datetime import datetime
from dateutil.relativedelta import relativedelta

print 'Today: ',datetime.now().strftime('%d/%m/%Y %H:%M:%S') 
date_after_month = datetime.now()+ relativedelta(day=1)
print 'After a Days:', date_after_month.strftime('%d/%m/%Y %H:%M:%S')

Output:

Today: 25/06/2015 20:41:44

After a Days: 01/06/2015 20:41:44

Community
  • 1
  • 1
Atul Arvind
  • 16,054
  • 6
  • 50
  • 58
10

Most Simplest solution

from datetime import timedelta, datetime
date = datetime(2003,8,1,12,4,5)
for i in range(5):
    date += timedelta(days=1)
    print(date)
Kiran Patil
  • 103
  • 1
  • 2
8

This was a straightforward solution for me:

from datetime import timedelta, datetime

today = datetime.today().strftime("%Y-%m-%d")
tomorrow = datetime.today() + timedelta(1)

Aus_10
  • 670
  • 7
  • 15
  • This does not answer OP question directly, because it assumes `today()` and is not as good as the accepted answer because it assumes default increment unit is `days`. – MarkHu Sep 15 '20 at 21:57
  • @MarkHu I'm not arguing my answer should be accepted. But could you elaborate on what the assumption is for ```today()``` and why it is a bad assumption? Also isn't the question asking for days? Is the statement that the accepted answer is a more general one? – Aus_10 Sep 16 '20 at 01:50
  • 1. The OP asked how to find the next day after an arbitrary date, not today. Your example code assigned a variable named `today` as a string, then never used it. Better: `date = datetime.today()` 2. Your last line hardcoded `today()` and assumed the first arg of `timedelta` is `days` (which happens to be correct, but why not name it for clarity?) Better: `laterDate = date + timedelta(days=1)` # IMHO :) – MarkHu Sep 17 '20 at 17:46
0

You can also import timedelta so the code is cleaner.

from datetime import datetime, timedelta
date = datetime.now() + timedelta(seconds=[delta_value])

Then convert to date to string

date = date.strftime('%Y-%m-%d %H:%M:%S')

Python one liner is

date = (datetime.now() + timedelta(seconds=[delta_value])).strftime('%Y-%m-%d %H:%M:%S')
Roy
  • 9
  • 1
-5

A short solution without libraries at all. :)

d = "8/16/18"
day_value = d[(d.find('/')+1):d.find('/18')]
tomorrow = f"{d[0:d.find('/')]}/{int(day_value)+1}{d[d.find('/18'):len(d)]}".format()
print(tomorrow)
# 8/17/18

Make sure that "string d" is actually in the form of %m/%d/%Y so that you won't have problems transitioning from one month to the next.

ZF007
  • 3,708
  • 8
  • 29
  • 48
Ace Pash
  • 1
  • 2
  • 5
  • 4
    if you set `d` to `8/31/18` then this returns `8/32/18`. If you change the year from `18`, it just breaks. – andrewsi Jan 09 '20 at 16:51
  • `datetime` is a standard library, it's already included in python and there's no penalty for using it. It's actually the other way around. – bluesmonk Nov 30 '22 at 11:19