Does python offer a way to easily get the current week of the month (1:4) ?
-
1When you reach the 29th, you are actually in the fifth week, right? – erikbstack Sep 27 '10 at 17:59
-
1Does a week start on the first day of the month or always on Monday? Or always on Sunday? Or... ? – Mark Byers Sep 27 '10 at 18:02
-
1"week of the month" is not exactly a commonly used concept. You need to tell us what is your definition, with examples, of "week of the month" ... in particular, week of WHICH month e.g. week starts on Monday, suppose today is both Sunday and the first day of the month: do you want (previous month, week 5) or (current month, week -1 or 0) or something else? – John Machin Sep 28 '10 at 00:47
-
Here's one definition: http://download-llnw.oracle.com/javase/1.3/docs/api/java/util/GregorianCalendar.html – John Machin Sep 28 '10 at 01:04
-
Mark Byers answer went straight to the point. I'm accessing an Oracle DB with cx_Oracle and trying to optimize the computation time passing queries already with the month and week of the month(the table is partitioned by month and subpartitioned by week of the month, which John Machin link has a definition as: "WEEK_OF_MONTH field range from .. 1 to .. 5") – Joao Figueiredo Sep 28 '10 at 11:07
-
Just to clarify, this was to avoid using PARTITION_KEY = ((TO_CHAR(SYSDATE, 'MM'))-1) and SUBPARTITION_WEEK = TO_NUMBER(TO_CHAR(SYSDATE, 'W')) as it would invalidate the index use. Passing the query with the correct numbers allows using the indexes. – Joao Figueiredo Sep 28 '10 at 11:19
23 Answers
In order to use straight division, the day of month for the date you're looking at needs to be adjusted according to the position (within the week) of the first day of the month. So, if your month happens to start on a Monday (the first day of the week), you can just do division as suggested above. However, if the month starts on a Wednesday, you'll want to add 2 and then do the division. This is all encapsulated in the function below.
from math import ceil
def week_of_month(dt):
""" Returns the week of the month for the specified date.
"""
first_day = dt.replace(day=1)
dom = dt.day
adjusted_dom = dom + first_day.weekday()
return int(ceil(adjusted_dom/7.0))

- 12,896
- 4
- 48
- 49
-
7adjusted_dom = (1 + first_day.weekday()) % 7 for week starting sunday – Justin Poehnelt Mar 03 '14 at 18:13
-
-
If i want to search second saturdays of each month, It will fail at 7th september 2019. – bhushan pardhi Nov 08 '19 at 11:39
-
1for March 4, 2020 this returns 2, which is incorrect. Switched to another solution below: https://stackoverflow.com/a/26662038/6072151 – Steve May 08 '20 at 16:53
-
5@JustinPoehnelt I think you've made a mistake. It should be `adjusted_dom = dom + (1 + first_day.weekday()) % 7` – user3595632 Sep 05 '20 at 00:08
-
@Steve I think you are considering that the week starts on Sunday instead of Monday. This function works perfect for those that consider the later – pakobill May 04 '22 at 15:59
I know this is years old, but I spent a lot of time trying to find this answer. I made my own method and thought I should share.
The calendar module has a monthcalendar method that returns a 2D array where each row represents a week. For example:
import calendar
calendar.monthcalendar(2015,9)
result:
[[0,0,1,2,3,4,5],
[6,7,8,9,10,11,12],
[13,14,15,16,17,18,19],
[20,21,22,23,24,25,26],
[27,28,29,30,0,0,0]]
So numpy's where is your friend here. And I'm in USA so I want the week to start on Sunday and the first week to be labelled 1:
import calendar
import numpy as np
calendar.setfirstweekday(6)
def get_week_of_month(year, month, day):
x = np.array(calendar.monthcalendar(year, month))
week_of_month = np.where(x==day)[0][0] + 1
return(week_of_month)
get_week_of_month(2015,9,14)
returns
3

- 393
- 3
- 5
-
sorry, i am novice to this. How do i use this function to get week number of current date instead of inserting exact year, month and date? – RSM May 10 '20 at 19:05
-
-
2using numpy for this one function is overkill - In my opinion. – Tony Suffolk 66 Sep 18 '20 at 19:03
If your first week starts on the first day of the month you can use integer division:
import datetime day_of_month = datetime.datetime.now().day week_number = (day_of_month - 1) // 7 + 1

- 811,555
- 193
- 1,581
- 1,452
-
maybe datetime.datetime.now().day would give the today's day in the month – aeter Sep 27 '10 at 18:11
-
Thanks. It turns out it wasn't about Python after all, but about arithmetics :) – Joao Figueiredo Sep 28 '10 at 11:00
-
2It's not clear to me that this works. Assume your week starts on a Monday and the 1st for the month of interest is a Sunday, you'd want day of month 1 to map to week of month 1. The algorithm above will return the correct answer in this case. However, if you move to the second day, a Monday the 2nd, you'd want the algorithm to return a 2. In this case, the algorithm returns the wrong answer. Please see my answer below which returns the correct result in both cases by accounting for the offset. – Josh May 29 '13 at 02:23
-
It fails for the date Feb 10th 2020 case and most other cases too .It is not a generic one – saravanan saminathan Mar 11 '20 at 10:44
Check out the package Pendulum
>>> dt = pendulum.parse('2018-09-30')
>>> dt.week_of_month
5

- 323
- 3
- 11
-
1I've been using that solution until 2021-01-10, 2021-01-17, 2021-01-24, 2021-01-31 dates return minus values as that, respectively: -51, -50, -49, -48.. So it's kind of buggy. – Gunner1905 Jul 06 '21 at 08:20
This version could be improved but as a first look in python modules (datetime and calendar), I make this solution, I hope could be useful:
from datetime import datetime
n = datetime.now()
#from django.utils.timezone import now
#n = now() #if you use django with timezone
from calendar import Calendar
cal = Calendar() # week starts Monday
#cal = Calendar(6) # week stars Sunday
weeks = cal.monthdayscalendar(n.year, n.month)
for x in range(len(weeks)):
if n.day in weeks[x]:
print x+1

- 499
- 10
- 13
Josh's answer has to be tweaked slightly to accomodate the first day falling on a Sunday.
def get_week_of_month(date):
first_day = date.replace(day=1)
day_of_month = date.day
if(first_day.weekday() == 6):
adjusted_dom = (1 + first_day.weekday()) / 7
else:
adjusted_dom = day_of_month + first_day.weekday()
return int(ceil(adjusted_dom/7.0))

- 1,070
- 2
- 16
- 20
def week_of_month(date_value):
week = date_value.isocalendar()[1] - date_value.replace(day=1).isocalendar()[1] + 1
return date_value.isocalendar()[1] if week < 0 else week
date_value should in timestamp format This will give the perfect answer in all the cases. It is purely based on ISO calendar

- 584
- 1
- 5
- 18
-
If you insert any date from 2021-1-4 to 2021-1-31, you will get a large negative number. This does not work in all cases. – Luke Dupin Apr 04 '22 at 20:17
-
1@LukeDupin Thanks for the criticism. Corrected the above code – saravanan saminathan Apr 06 '22 at 02:18
Check out the python calendar module

- 4,228
- 7
- 26
- 24
-
Thanks. I knew about calendar and dateutil, but both didn't help me at that. – Joao Figueiredo Sep 28 '10 at 10:59
-
1vito has the right answer. I used: `st, end = calendar.monthrange(2012, 6)`, `days = range(st, end+1)`, `week_days = [days[i : i+7] for i in range(0, len(days), 7)]` – yurisich Jun 06 '12 at 15:01
-
data['wk_of_mon'] = (data['dataset_date'].dt.day - 1) // 7 + 1

- 21
- 1
- 3
-
This solution is already provided in another answer. If you have any different solution please mention it. If there is any change/extension required to the original answer, then edit it. – Azhar Khan Dec 17 '22 at 09:43
I found a quite simple way:
import datetime
def week(year, month, day):
first_week_month = datetime.datetime(year, month, 1).isocalendar()[1]
if month == 1 and first_week_month > 10:
first_week_month = 0
user_date = datetime.datetime(year, month, day).isocalendar()[1]
if month == 1 and user_date > 10:
user_date = 0
return user_date - first_week_month
returns 0 if first week
-
`isocalendar()` can return 53 for January 1. Your implementation returns -52 for `weekOfMonth(2010, 1, 8)`. – Adam Rosenfield Dec 06 '10 at 23:08
-
1I fixed the code with a check for that error, and the code doesn´t get that big and it does the job perfectly. – Manuel Cuadra Leighton Dec 07 '10 at 00:57
-
-
Josh' answer seems the best but I think that we should take into account the fact that a week belongs to a month only if its Thursday falls into that month. At least that's what the iso says.
According to that standard, a month can have up to 5 weeks. A day could belong to a month, but the week it belongs to may not.
I have taken into account that just by adding a simple
if (first_day.weekday()>3) :
return ret_val-1
else:
return ret_val
where ret_val is exactly Josh's calculated value. Tested on June 2017 (has 5 weeks) and on September 2017. Passing '2017-09-01' returns 0 because that day belongs to a week that does not belong to September.
The most correct way would be to have the method return both the week number and the month name the input day belongs to.

- 941
- 6
- 10
A variation on @Manuel Solorzano's answer:
from calendar import monthcalendar
def get_week_of_month(year, month, day):
return next(
(
week_number
for week_number, days_of_week in enumerate(monthcalendar(year, month), start=1)
if day in days_of_week
),
None,
)
E.g.:
>>> get_week_of_month(2020, 9, 1)
1
>>> get_week_of_month(2020, 9, 30)
5
>>> get_week_of_month(2020, 5, 35)
None

- 1,213
- 12
- 26
Say we have some month's calender as follows:
Mon Tue Wed Thur Fri Sat Sun
1 2 3
4 5 6 7 8 9 10
We say day 1 ~ 3 belongs to week 1 and day 4 ~ 10 belongs to week 2 etc.
In this case, I believe the week_of_month for a specific day should be calculated as follows:
import datetime
def week_of_month(year, month, day):
weekday_of_day_one = datetime.date(year, month, 1).weekday()
weekday_of_day = datetime.date(year, month, day)
return (day - 1)//7 + 1 + (weekday_of_day < weekday_of_day_one)
However, if instead we want to get the nth of the weekday that date is, such as day 1 is the 1st Friday, day 8 is the 2nd Friday, and day 6 is the 1st Wednesday, then we can simply return (day - 1)//7 + 1

- 11
- 1
-
It works well, but we need: weekday_of_day = datetime.date(year, month, day).weekday() – yeharav Oct 10 '20 at 07:01
The answer you are looking for is (dm-dw+(dw-dm)%7)/7+1
where dm
is the day of the month, dw
is the day of the week, and %
is the positive remainder.
This comes from relating the month offset (mo
) and the week of the month (wm
), where the month offset is how far into the week the first day starts. If we consider all of these variables to start at 0 we have
wm*7+dw = dm+mo
You can solve this modulo 7 for mo
as that causes the wm
variable drops out as it only appears as a multiple of 7
dw = dm+mo (%7)
mo = dw-dm (%7)
mo = (dw-dm)%7 (since the month offset is 0-6)
Then you just substitute the month offset into the original equation and solve for wm
wm*7+dw = dm+mo
wm*7 = dm-dw + mo
wm*7 = dm-dw + (dw-dm)%7
wm = (dm-dw + (dw-dm)%7) / 7
As dm
and dw
are always paired, these can be offset by any amount, so, switching everything to start a 1 only changes the the equation to (dm-dw + (dw-dm)%7)/7 + 1
.
Of course the python datetime
library starts dm
at 1 and dw
at 0. So, assuming date
is a datatime.date
object, you can go with
(date.day-1-date.dayofweek() + (date.dayofweek()-date.day+1)%7) / 7 + 1
As the inner bit is always a multiple of 7 (it is literally dw*7
), you can see that the first -date.dayofweek()
simply adjusts the value backwards to closest multiple of 7. Integer division does this too, so it can be further simplified to
(date.day-1 + (date.dayofweek()-date.day+1)%7) // 7 + 1
Be aware that dayofweek()
puts Sunday at the end of the week.

- 11
- 2
-
Thank you for you answer. It is 100% correct. I've tested this one by using the calendar.monthcalendar as a source of truth and iterating from datetime.date.min up to datetime.date.max and the results were the same. I just needed to change daysofweek() -> weekday() and remove the +1 at the end. Please check out this Gist for more details. https://gist.github.com/klement97/0912e56a8023741e87201fac0da261cd – klement omeri Aug 07 '21 at 20:47
This should do it.
#! /usr/bin/env python2
import calendar, datetime
#FUNCTIONS
def week_of_month(date):
"""Determines the week (number) of the month"""
#Calendar object. 6 = Start on Sunday, 0 = Start on Monday
cal_object = calendar.Calendar(6)
month_calendar_dates = cal_object.itermonthdates(date.year,date.month)
day_of_week = 1
week_number = 1
for day in month_calendar_dates:
#add a week and reset day of week
if day_of_week > 7:
week_number += 1
day_of_week = 1
if date == day:
break
else:
day_of_week += 1
return week_number
#MAIN
example_date = datetime.date(2015,9,21)
print "Week",str(week_of_month(example_date))
#Returns 'Week 4'

- 1
- 1
Move to last day of week in month and divide to 7
from math import ceil
def week_of_month(dt):
""" Returns the week of the month for the specified date.
"""
# weekday from monday == 0 ---> sunday == 6
last_day_of_week_of_month = dt.day + (7 - (1 + dt.weekday()))
return int(ceil(last_day_of_week_of_month/7.0))

- 947
- 7
- 8
You can simply do as follow:
- First extract the month and the week of year number
df['month'] = df['Date'].dt.month
df['week'] = df['Date'].dt.week
- Then group by month and rank the week numbers
df['weekOfMonth'] = df.groupby('month')["week"].rank("dense", ascending=False)

- 93
- 6
One more solution, where Sunday is first day of week, base Python only.
def week_of_month(dt):
""" Returns the week of the month for the specified date.
TREATS SUNDAY AS FIRST DAY OF WEEK!
"""
first_day = dt.replace(day=1)
dom = dt.day
adjusted_dom = dom + (first_day.weekday() + 1) % 7
return (adjusted_dom - 1) // 7 + 1

- 25
- 4
-
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](https://stackoverflow.com/help/how-to-answer). – Ethan Jun 17 '22 at 18:42
def week_number(time_ctime = None):
import time
import calendar
if time_ctime == None:
time_ctime = str(time.ctime())
date = time_ctime.replace(' ',' ').split(' ')
months = {'Jan':1,'Feb':2,'Mar':3,'Apr':4,'May':5,'Jun':6,'Jul':7,'Aug':8,'Sep':9,'Oct':10,'Nov':11,'Dec':12}
week, day, month, year = (-1, str(date[2]), months[date[1]], int(date[-1]))
cal = calendar.monthcalendar(year,month)
for wk in range(len(cal)):
wstr = [str(x) for x in cal[wk]]
if day in wstr:
week = wk
break
return week
import time
print(week_number())
print(week_number(time.ctime()))

- 1
- 1
-
Welcome to Stack Overflow. Code is a lot more helpful when it is accompanied by an explanation. Stack Overflow is about learning, not providing snippets to blindly copy and paste. Please [edit] your answer and explain how it answers the specific question being asked. See [answer]. – ChrisGPT was on strike Jul 07 '22 at 15:39
An Easy way to get a week number of month;
if the datatype is datetime64 then
week_number_of_month = date_value.dayofweek

- 21
- 3
the best solution that I found is this function
def get_week_of_month(date):
date = datetime.strptime(date, "%Y-%m-%d") # date is str
first_day = date.replace(day=1)
print(first_day)
day_of_month = date.day
print(day_of_month)
print(first_day.weekday())
if(first_day.weekday() == 6):
adjusted_dom = day_of_month + ((1 + first_day.weekday()) / 7)
else:
adjusted_dom = day_of_month + first_day.weekday()
print(adjusted_dom)
return int(ceil(adjusted_dom/7.0))

- 15
- 7
-
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 Jan 27 '23 at 12:13
This solution was intended to replicate the Java implementation of WeekOfMonth in Python and follow a pattern similar to the ISO 8601 convention.
First day of the week is Monday
Minimal number of days in the first week is 4. This implies weeks starting on and between Monday and Thursday inclusive are full weeks
from datetime import date def week_of_month(calendar_date: date) -> int: """ Python implementation of Week of Month following ISO 8601 https://en.wikipedia.org/wiki/ISO_week_date, 1. First day of the week is Monday 2. Minimal days in the first week is 4 so weeks starting on and between Monday and Thursday inclusive are full weeks This function returns the week's number within a month for a calendar date :param calendar_date: :return: week of the month """ _, month, _ = calendar_date.year, \ calendar_date.month, \ calendar_date.day _, week_of_year, _ = calendar_date.isocalendar() date_at_month_start = calendar_date.replace(day=1) _, month_start_week_of_year, month_start_day_of_week = \ date_at_month_start.isocalendar() if month == 1: return 0 if week_of_year >= 51 else week_of_year elif month_start_day_of_week > 4: return week_of_year - month_start_week_of_year else: return week_of_year - month_start_week_of_year + 1

- 1
- 1
import datetime
def week_number_of_month(date_value):
week_number = (date_value.isocalendar()[1] - date_value.replace(day=1).isocalendar()[1] + 1)
if week_number == -46:
week_number = 6
return week_number
date_given = datetime.datetime(year=2018, month=12, day=31).date()
week_number_of_month(date_given)

- 4,117
- 1
- 23
- 17
-
datetime.datetime(year=2021, month=1, day=8).date() Above case failed for this input – saravanan saminathan Apr 06 '22 at 02:20