72

i know using datetime.timedelta i can get the date of some days away form given date

daysafter = datetime.date.today() + datetime.timedelta(days=5)

but seems no datetime.timedelta(month=1)

Mad Physicist
  • 107,652
  • 25
  • 181
  • 264
icn
  • 17,126
  • 39
  • 105
  • 141

13 Answers13

211

Use dateutil module. It has relative time deltas:

import datetime
from dateutil import relativedelta
nextmonth = datetime.date.today() + relativedelta.relativedelta(months=1)

Beautiful.

Stephen Fuhry
  • 12,624
  • 6
  • 56
  • 55
nosklo
  • 217,122
  • 57
  • 293
  • 297
45

Of course there isn't -- if today's January 31, what would be "the same day of the next month"?! Obviously there is no right solution, since February 31 does not exist, and the datetime module does not play at "guess what the user posing this impossible problem without a right solution thinks (wrongly) is the obvious solution";-).

I suggest:

try:
  nextmonthdate = x.replace(month=x.month+1)
except ValueError:
  if x.month == 12:
    nextmonthdate = x.replace(year=x.year+1, month=1)
  else:
    # next month is too short to have "same date"
    # pick your own heuristic, or re-raise the exception:
    raise
Alex Martelli
  • 854,459
  • 170
  • 1,222
  • 1,395
  • 2
    Thanks Alex! I used to use Datetime.AddMonths() in c# for this question. So i didn't even think much before asking the dump question :). I did a test with c# Datetime.AddMonths(1) for Jan (28-31), interesting results, i got 5 Feb 28. Thanks again Alex! – icn Feb 12 '10 at 06:38
9

You can use calendar.nextmonth (from Python 3.7).

>>> import calendar
>>> calendar.nextmonth(year=2019, month=6)
(2019, 7)
>>> calendar.nextmonth(year=2019, month=12)
(2020, 1)

But be aware that this function isn't meant to be public API, it's used internally in calendar.Calendar.itermonthdays3() method. That's why it doesn't check the given month value:

>>> calendar.nextmonth(year=2019, month=60)
(2019, 61)

In Python 3.8 is already implemented as internal function.

balrog
  • 3
  • 2
icoxfog417
  • 137
  • 1
  • 4
  • Presumably, this internal will be stable for a while. But unfortunately can't be trusted not to change, right? I wonder why this function isn't made available as a non-internal. – Rob Sep 05 '22 at 21:09
8
from calendar import mdays
from datetime import datetime, timedelta

today = datetime.now()
next_month_of_today = today + timedelta(mdays[today.month])

I don't want to import dateutil. Have a try this. Good luck.

zerone
  • 97
  • 1
  • 2
  • 3
    I really wanted this solution to work but one year in 4 February will be broken using mdays... – Zemogle Apr 12 '12 at 02:18
  • 1
    mdays isn't even exposed in the documentation, probably for the very reason that mdays is not accurate for leap-years. the 'monthrange' function is more accurate, as it takes this into account. – Ch'marr May 16 '12 at 21:02
7
import calendar, datetime

def next_month ( date ):
    """return a date one month in advance of 'date'. 
    If the next month has fewer days then the current date's month, this will return an
    early date in the following month."""
    return date + datetime.timedelta(days=calendar.monthrange(date.year,date.month)[1])
Ch'marr
  • 1,284
  • 11
  • 8
  • 3
    this is wrong. `next_month(datetime.date(2014,01,30)) == datetime.date(2014, 3, 2)` – fjsj Sep 01 '14 at 22:11
5

This work for me

import datetime
import calendar


def next_month_date(d):
    _year = d.year+(d.month//12)
    _month =  1 if (d.month//12) else d.month + 1
    next_month_len = calendar.monthrange(_year,_month)[1]
    next_month = d
    if d.day > next_month_len:
        next_month = next_month.replace(day=next_month_len)
    next_month = next_month.replace(year=_year, month=_month)
    return next_month

usage:

d = datetime.datetime.today()
print next_month_date(d)
Daoctor
  • 412
  • 5
  • 8
3

This is how I solved it.

from datetime import datetime, timedelta
from calendar import monthrange

today_date = datetime.now().date()  # 2021-10-29
year = today_date.year
month = today_date.month

days_in_month = monthrange(year, month)[1]
next_month = today_date + timedelta(days=days_in_month)
print(next_month)  # 2021-11-29
Tech Amit
  • 31
  • 1
3

Solution on Python3 without additional modules nor internal functions.

from datetime import date
today = date.today()
nextMonth = date(today.year+((today.month+1)//12) , ((today.month+1)%12), today.day)

Hurray for integer algebra!

  • This fails if today is 1/31/22. Test using ```from datetime import datetime today = datetime(2022, 1, 31) ``` – Rob Sep 06 '22 at 05:57
  • 1
    @Rob is right, this will throw ValueError exception. You can use relativedelta of dateutil. – bhargav3vedi Aug 08 '23 at 07:46
1
from datetime import timedelta
try:
    next_month = (x.replace(day=28) + timedelta(days=7)).replace(day=x.day)
except ValueError:  # assuming January 31 should return last day of February.
    next_month = (x + timedelta(days=31)).replace(day=1) - timedelta(days=1)
Collin Anderson
  • 14,787
  • 6
  • 68
  • 57
1

This Code Works for me:

NextMonth = self.CurruntMonth.replace(day=15) + datetime.timedelta(days=30)
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community May 30 '22 at 11:01
1
from dateutil.relativedelta import relativedelta
from dateutil import parser
d2 = "1/4/2022 8:39:23 AM"
NextMonth = parser.parse(d2) + relativedelta(months=+1) + relativedelta(days=-1)
print(NextMonth)
gzbuzz
  • 11
  • 1
0

This is how I solved it.

from datetime import date
try:
    (year, month) = divmod(date.today().month, 12)
    next_month = date.today().replace(year=date.today().year+year, month=month+1)
except ValueError:
    # This day does not exist in next month

You can skip the try/catch if you only want the first day in next month by setting replace(year=date.today().year+year, month=month, day=1). This will always be a valid date since we have caught the month overflow using divmod.

Hans Kristian
  • 1,786
  • 19
  • 25
0

I often need to need to keep the date as last in month when adding months. I try to add the amount of months to the day after and then remove one day again. If that fails I add one more day until success.

from datetime import timedelta

DAY = timedelta(1)

def add_months(d, months):
    "Add months to date and retain last day in month."
    d += DAY
    # calculate year diff and zero based month
    y, m = divmod(d.month + months - 1, 12)
    try:
        return d.replace(d.year + y, m + 1) - DAY
    except ValueError:
        # on fail return last day in month
        # can't fail on december so just adding one more month
        return d.replace(d.year + y, m + 2, 1) - DAY
Jolbas
  • 757
  • 5
  • 15