Given a particular date, say 2011-07-02, how can I find the date of the next Monday (or any weekday day for that matter) after that date?
-
2http://docs.python.org/library/datetime.html#datetime.date.weekday – Juan Gomez Jul 02 '11 at 17:43
13 Answers
import datetime
def next_weekday(d, weekday):
days_ahead = weekday - d.weekday()
if days_ahead <= 0: # Target day already happened this week
days_ahead += 7
return d + datetime.timedelta(days_ahead)
d = datetime.date(2011, 7, 2)
next_monday = next_weekday(d, 0) # 0 = Monday, 1=Tuesday, 2=Wednesday...
print(next_monday)

- 278,196
- 72
- 453
- 469
-
9
-
6@jstaab Or simplify to `(day - today) % 7`. Negative results in the subtraction will be treated as you expect. For example `-1 % 7` gives `6`. – Code-Apprentice Aug 24 '20 at 17:49
Here's a succinct and generic alternative to the slightly weighty answers above.
def onDay(date, day):
"""
Returns the date of the next given weekday after
the given date. For example, the date of next Monday.
NB: if it IS the day we're looking for, this returns 0.
consider then doing onDay(foo, day + 1).
"""
days = (day - date.weekday() + 7) % 7
return date + datetime.timedelta(days=days)

- 28,235
- 9
- 60
- 81

- 1,054
- 9
- 9
-
2Clean but needs two reminders. 1. This returns same date if the weekdays match for day and date.weekday() 2. day should be in the weekday() format, not isoweekday() – bhtabor Feb 07 '19 at 16:49
-
10Works, but the `+7` is unnecessary when you are taking `%7`. Change it to: `onDay = lambda date, day: date + datetime.timedelta(days=(day-date.weekday())%7)` – Zach Siegel May 15 '19 at 20:33
-
3Also, since Python's `datetime` package has a `date` class (that I personally frequently import), I treat `date` as a keyword and don't name variables `date`. I would change this to: `onDay = lambda dt, day: dt + datetime.timedelta(days=(day-dt.weekday())%7)` to remind myself that the format of the input is a Python `datetime.date` variable. (Also, in Javascript, `date` is a standard type, and you shouldn't name variables `date`.) – Zach Siegel May 15 '19 at 20:37
-
1To address bhtabor's issues: 1. To make sure next week's Monday is returned, even if `date` itself is a Monday, change to `onDay = lambda date, day: date + datetime.timedelta(days=(day-date.weekday()-1)%7+1)`. Less importantly: 2. change `date.weekday()` to `date.isoweekday()` if `day` should be a value 1..7 instead of 0..6 for Monday..Sunday. – ElRudi Jun 15 '20 at 22:08
Try
>>> dt = datetime(2011, 7, 2)
>>> dt + timedelta(days=(7 - dt.weekday()))
datetime.datetime(2011, 7, 4, 0, 0)
using, that the next monday is 7 days after the a monday, 6 days after a tuesday, and so on, and also using, that Python's datetime
type reports monday as 0
, ..., sunday as 6
.

- 30,623
- 8
- 82
- 102
-
Interesting that - when I try to find the upcoming Sunday after datetime(2013, 1, 1) with "datetime(2013, 1, 1) + timedelta(days=(7 - datetime(2013, 1, 1).weekday()))", I get "datetime.datetime(2013, 1, 7, 0, 0)", which is a Monday. – fixxxer Jun 11 '13 at 14:28
-
2@fixxxer - As it says in the answer: the code uses a few properties of the `datetime` API in ways, which will only work, if you are looking for mondays. The code provided by `phihag` is more general and can find any upcoming day-of-week. – Dirk Jun 11 '13 at 15:35
-
-
@fixxxer: Why don't you simply use the code provided by `phihag`? It can do what you want: `next_weekday(datetime.date(2013,1,1), 6)` is `datetime.date(2013, 1, 6)`, a sunday. My code is "cute" in (ab)using certain properties of python's `datetime` API and answers only the "find the next **monday**" part of the question, but not general enough to answer the "find the next *xxx*day" question. – Dirk Jun 12 '13 at 09:32
-
@fixxxer: to find the next Sunday using "cute" code: `d + timedelta(6 - d.weekday() or 13 - d.weekday())` (it is equivalent to phihag's code if `Sunday == 6` is the last day of the week) – jfs Oct 07 '15 at 17:24
This is example of calculations within ring mod 7
.
import datetime
def next_day(given_date, weekday):
day_shift = (weekday - given_date.weekday()) % 7
return given_date + datetime.timedelta(days=day_shift)
now = datetime.date(2018, 4, 15) # sunday
names = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday',
'saturday', 'sunday']
for weekday in range(7):
print(names[weekday], next_day(now, weekday))
will print:
monday 2018-04-16
tuesday 2018-04-17
wednesday 2018-04-18
thursday 2018-04-19
friday 2018-04-20
saturday 2018-04-21
sunday 2018-04-15
As you see it's correctly give you next monday, tuesday, wednesday, thursday friday and saturday. And it also understood that 2018-04-15
is a sunday and returned current sunday instead of next one.
I'm sure you'll find this answer extremely helpful after 7 years ;-)

- 2,061
- 1
- 19
- 18
Another alternative uses rrule
from dateutil.rrule import rrule, WEEKLY, MO
from datetime import date
next_monday = rrule(freq=WEEKLY, dtstart=date.today(), byweekday=MO, count=1)[0]
rrule docs: https://dateutil.readthedocs.io/en/stable/rrule.html

- 685
- 7
- 12
-
This was the answer I needed. The `relativedelta` version worked fine until after the time on the given day. E.g. when requesting the next Monday at 11:00 and the start time is Monday at 13:00, `relativedelta` will still return the present day at 11:00—which is in the past. `rrule`, on the other hand, looks for the next instance after `dtstart`. So it will correctly return Monday at 11:00 for a `dtstart` of Monday at 10:00 and then _next_ Monday at 11 for a `dtstart` of Monday at 13:00. – Nick K9 Mar 24 '23 at 17:18
-
Another simple elegant solution is to use pandas offsets.
I find it very helpful and robust when playing with dates.
- If you want the first Sunday just modify the frequency to freq='W-SUN'.
- If you want a couple of next Sundays, change the offsets.Day(days).
- Using pandas offsets allow you to ignore holidays, work only with Business Days and more.
You can also apply this method easily on a whole DataFrame using the apply
method.
import pandas as pd
import datetime
# 1. Getting the closest monday from a given date
date = datetime.date(2011, 7, 2)
closest_monday = pd.date_range(start=date, end=date + pd.offsets.Day(6), freq="W-MON")[
0
]
# 2. Adding a 'ClosestMonday' column with the closest monday for each row in
# a pandas df using apply. Requires you to have a 'Date' column in your df
def get_closest_monday(row):
return pd.date_range(
start=row.Date, end=row.Date + pd.offsets.Day(6), freq="W-MON"
)[0]
df = pd.DataFrame([datetime.date(2011, 7, 2)], columns=["Date"])
df["ClosestMonday"] = df.apply(lambda row: get_closest_monday(row), axis=1)
print(df)

- 1,248
- 12
- 14

- 71
- 1
- 3
-
Yes, `date_range` + `W-MON` + `offsets.Day(6)` is *the* elegant solution to the query "every Monday between fixed date in the past and now", all without manual fiddling with weekdays. Thanks! This answer should have more votes. – ojdo Feb 08 '21 at 11:08
-
You can start adding one day to date object and stop when it's monday.
>>> d = datetime.date(2011, 7, 2)
>>> while d.weekday() != 0: #0 for monday
... d += datetime.timedelta(days=1)
...
>>> d
datetime.date(2011, 7, 4)

- 26,532
- 10
- 62
- 81
dateutil has a special feature for this kind of operation and it's the most elegant way I have ever seen yet.
from datetime import datetime
from dateutil.relativedelta import relativedelta, MO
first_monday_date = (datetime(2011,7,2) + relativedelta(weekday=MO(0))).date()
if you want datetime just
first_monday_date = datetime(2011,7,2) + relativedelta(weekday=MO(0))

- 180
- 2
- 16
import datetime
d = datetime.date(2011, 7, 2)
while d.weekday() != 0:
d += datetime.timedelta(1)

- 13,947
- 17
- 94
- 123
weekday = 0 ## Monday
dt = datetime.datetime.now().replace(hour=0, minute=0, second=0) ## or any specific date
days_remaining = (weekday - dt.weekday() - 1) % 7 + 1
next_dt = dt + datetime.timedelta(days_remaining)

- 4,110
- 2
- 31
- 48
This will give the first next Monday after given date:
import datetime
def get_next_monday(year, month, day):
date0 = datetime.date(year, month, day)
next_monday = date0 + datetime.timedelta(7 - date0.weekday() or 7)
return next_monday
print get_next_monday(2011, 7, 2)
print get_next_monday(2015, 8, 31)
print get_next_monday(2015, 9, 1)
2011-07-04
2015-09-07
2015-09-07

- 13,930
- 3
- 20
- 15
Generally to find any date from day of week from today:
def getDateFromDayOfWeek(dayOfWeek):
week_days = ["monday", "tuesday", "wednesday",
"thursday", "friday", "saturday", "sunday"]
today = datetime.datetime.today().weekday()
requiredDay = week_days.index(dayOfWeek)
if today>requiredDay:
noOfDays=7-(today-requiredDay)
print("noDays",noOfDays)
else:
noOfDays = requiredDay-today
print("noDays",noOfDays)
requiredDate = datetime.datetime.today()+datetime.timedelta(days=noOfDays)
return requiredDate
print(getDateFromDayOfWeek('sunday').strftime("%d/%m/%y"))
Gives output in format of Day/Month/Year

- 55
- 1
- 7
via list comprehension?
from datetime import *
[datetime.today()+timedelta(days=x) for x in range(0,7) if (datetime.today()+timedelta(days=x)).weekday() % 7 == 0]
(0 at the end is for next monday, returns current date when run on monday)

- 1