95

How do I find the previous Monday's date, based off of the current date using Python? I thought maybe I could use: datetime.weekday() to do it, but I am getting stuck.

I basically want to find today's date and Mondays date to construct a date range query in django using: created__range=(start_date, end_date).

acrosman
  • 12,814
  • 10
  • 39
  • 55
Joe
  • 4,553
  • 9
  • 51
  • 57

8 Answers8

208
>>> import datetime
>>> today = datetime.date.today()
>>> today + datetime.timedelta(days=-today.weekday(), weeks=1)
datetime.date(2009, 10, 26)

Some words of explanation:

Take todays date. Subtract the number of days which already passed this week (this gets you 'last' monday). Add one week.

Edit: The above is for 'next monday', but since you were looking for 'last monday' you could use

today - datetime.timedelta(days=today.weekday())
ChristopheD
  • 112,638
  • 29
  • 165
  • 179
  • 15
    Python is awesome :) This is difficult and non-trivial in most other languages. – gak Apr 26 '12 at 05:39
  • 3
    Doesn't actually answer question which was for last monday not next monday – Martin Spamer Feb 09 '15 at 11:08
  • 4
    @GeraldKaszuba actually it's much easier and more readable in PHP: `new DateTime("last monday")` or `strtotime("last monday")`. – JustAC0der Jan 11 '17 at 09:13
  • 1
    @JustAC0der How would you get the last monday before an arbitrary date, as opposed to today? – BallpointBen Mar 20 '18 at 14:33
  • 4
    @BallpointBen For example: `strtotime("last monday", strtotime("2018-03-14"))`, but I don't want to get into a discussion about which language is better. All languages have their drawbacks and advantages. – JustAC0der Mar 21 '18 at 11:19
  • 1
    The accepted solution for finding last Monday might not work for all cases. Example below: `>>> from datetime import date, timedelta >>> today = date(2020, 4, 6) >>> today - timedelta(days=today.weekday()) datetime.date(2020, 4, 6) >>> ` – sreenath sirimala Apr 10 '20 at 05:21
59

ChristopheD's post is close to what you want. I don't have enough rep to make a comment :(

Instead of (which actually gives you the next upcoming monday):

>>> today + datetime.timedelta(days=-today.weekday(), weeks=1)
datetime.date(2009, 10, 26)

I would say:

>>> last_monday = today - datetime.timedelta(days=today.weekday())

If you want the previous week, add the 'weeks=1' parameter.

This makes the code more readable since you are subtracting a timedelta. This clears up any confusion caused by adding a timedelta that has negative and positive offsets.

Steven Graham
  • 1,220
  • 8
  • 10
  • 17
    Whooohooo, I can comment now! Thanks. – Steven Graham Oct 26 '09 at 20:52
  • 1
    The above solution for finding last Monday might not work for all cases. Example below: `>>> from datetime import date, timedelta >>> today = date(2020, 4, 6) >>> today - timedelta(days=today.weekday()) datetime.date(2020, 4, 6) >>> ` – sreenath sirimala Apr 10 '20 at 05:23
26

I think the easiest way is using python-dateutil like this:

from datetime import date
from dateutil.relativedelta import relativedelta, MO

today = date.today()
last_monday = today + relativedelta(weekday=MO(-1))
print last_monday
Paul
  • 10,381
  • 13
  • 48
  • 86
diegueus9
  • 29,351
  • 16
  • 62
  • 74
16

Note: The OP says in the comments, "I was looking for the past Monday". I take this to mean we are looking for the last Monday that occurred strictly before today.

The calculation is a little difficult to get right using only the datetime module (especially given the above interpretation of "past Monday" and if you wish to avoid clunky if-statements). For example, if today is a Monday such as 2013-12-23,

today - DT.timedelta(days=today.weekday())

returns 2013-12-23, which is the same day as today (not the past Monday).

The advantage of using the dateutil module is that you don't have to do tricky mental calculations nor force the reader to do the same to get the right date. dateutil does it all for you:

import dateutil.relativedelta as rdelta
import datetime as DT

today = DT.date(2013, 12, 23)  # Monday

past_monday = today + rdelta.relativedelta(days=-1, weekday=rdelta.MO(-1))
print(past_monday)
# 2013-12-16

next_monday = today + rdelta.relativedelta(days=1, weekday=rdelta.MO(+1))
print(next_monday)
# 2013-12-30

Note that days=-1 is needed to guarantee that past_monday is a different day than today.

unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
8

For future googlers who show up on this page looking for a way to get "the most recent Sunday", rather than "the most recent Monday", you need to do some additional math because datetime.weekday() treats Monday as the first day of the week:

today = datetime.date.today()
weekday = today.weekday() + 1
start_day = today - datetime.timedelta(days=weekday % 7)

If today is Tuesday, this sets start_day to last Sunday. If today is Sunday, this sets start_day to today. Take away the % 7 if you want "last Sunday" to be a week ago if it's currently Sunday.

coredumperror
  • 8,471
  • 6
  • 33
  • 42
3

Using timedeltas and datetime module:

import datetime
datetime.date.today()+datetime.timedelta(days=-datetime.date.today().weekday())
elzapp
  • 1,961
  • 4
  • 15
  • 22
3

You can use Natty. I tried parsedatetime and dateparser. Comparing these three, I think Natty is the best one.

To get your result, use like this:

>>> from natty import DateParser
>>> dp = DateParser('last monday')
>>> dp.result()
[datetime.datetime(2016, 8, 1, 17, 35, 5, tzinfo=tzlocal())] #Today is 9th of August 2016 5.35 PM

Github Link : https://github.com/eadmundo/python-natty

Try it, It can do more!

AKA
  • 5,479
  • 4
  • 22
  • 36
1
d = datetime.datetime.today().weekday()

gives you today's day of the week, counting 0 (monday) to 6 (sunday)

datetime.datetime.today() + datetime.timedelta(days=(7-d)%7)

(7-d)%7 gives you days until Monday, or leaves you where you are if today is Monday

foosion
  • 7,619
  • 25
  • 65
  • 102