Find the date for the first Monday after a given date

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?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

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)

Method 2

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)

Method 3

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.

Method 4

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 😉

Method 5

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)

Method 6

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

Method 7

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)

Method 8

import datetime

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

Method 9

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)

Method 10

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

Method 11

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))

Method 12

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

Method 13

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)


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x