Skip to content

Commit c811ecd

Browse files
authored
Fix behavior of the week_of_month property (#774)
Fixes #438 Fixes #455 Fixes #536 Fixes #587 Fixes #598 Fixes #718
1 parent 1ff9a1c commit c811ecd

File tree

3 files changed

+47
-4
lines changed

3 files changed

+47
-4
lines changed

src/pendulum/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@
5050
SATURDAY = WeekDay.SATURDAY
5151
SUNDAY = WeekDay.SUNDAY
5252

53-
5453
_TEST_NOW: DateTime | None = None
5554
_LOCALE = "en"
5655
_WEEK_STARTS_AT: WeekDay = WeekDay.MONDAY

src/pendulum/date.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,7 @@ def days_in_month(self) -> int:
7474

7575
@property
7676
def week_of_month(self) -> int:
77-
first_day_of_month = self.replace(day=1)
78-
79-
return self.week_of_year - first_day_of_month.week_of_year + 1
77+
return math.ceil((self.day + self.first_of("month").isoweekday() - 1) / 7)
8078

8179
@property
8280
def age(self) -> int:

tests/datetime/test_getters.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,14 @@ def test_week_of_year_last_week():
195195
assert pendulum.datetime(2012, 12, 31).week_of_year == 1
196196

197197

198+
def test_week_of_month_edge_case():
199+
assert pendulum.datetime(2020, 1, 1).week_of_month == 1
200+
assert pendulum.datetime(2020, 1, 7).week_of_month == 2
201+
assert pendulum.datetime(2020, 1, 14).week_of_month == 3
202+
assert pendulum.datetime(2023, 1, 1).week_of_month == 1
203+
assert pendulum.datetime(2023, 1, 31).week_of_month == 6
204+
205+
198206
def test_timezone():
199207
d = pendulum.datetime(2000, 1, 1, tz="America/Toronto")
200208
assert d.timezone.name == "America/Toronto"
@@ -247,3 +255,41 @@ def test_time():
247255
t = dt.time()
248256
assert isinstance(t, pendulum.Time)
249257
assert_time(t, 10, 40, 34, 123456)
258+
259+
260+
@pytest.mark.parametrize(
261+
"date, expected",
262+
[
263+
(pendulum.Date(2000, 1, 1), 1),
264+
(pendulum.Date(2000, 1, 3), 2),
265+
(pendulum.Date(2019, 12, 29), 5),
266+
(pendulum.Date(2019, 12, 30), 6),
267+
(pendulum.Date(2019, 12, 31), 6),
268+
(pendulum.Date(2020, 1, 7), 2),
269+
(pendulum.Date(2020, 1, 14), 3),
270+
(pendulum.Date(2021, 1, 1), 1),
271+
(pendulum.Date(2021, 1, 2), 1),
272+
(pendulum.Date(2021, 1, 9), 2),
273+
(pendulum.Date(2021, 1, 10), 2),
274+
(pendulum.Date(2021, 1, 11), 3),
275+
(pendulum.Date(2021, 1, 15), 3),
276+
(pendulum.Date(2021, 1, 16), 3),
277+
(pendulum.Date(2021, 1, 17), 3),
278+
(pendulum.Date(2021, 1, 23), 4),
279+
(pendulum.Date(2021, 1, 31), 5),
280+
(pendulum.Date(2021, 12, 19), 3),
281+
(pendulum.Date(2021, 12, 25), 4),
282+
(pendulum.Date(2021, 12, 26), 4),
283+
(pendulum.Date(2021, 12, 29), 5),
284+
(pendulum.Date(2021, 12, 30), 5),
285+
(pendulum.Date(2021, 12, 31), 5),
286+
(pendulum.Date(2022, 1, 1), 1),
287+
(pendulum.Date(2022, 1, 3), 2),
288+
(pendulum.Date(2022, 1, 10), 3),
289+
(pendulum.Date(2023, 1, 1), 1),
290+
(pendulum.Date(2023, 1, 2), 2),
291+
(pendulum.Date(2029, 12, 31), 6),
292+
],
293+
)
294+
def test_week_of_month_negative(date, expected):
295+
assert date.week_of_month == expected

0 commit comments

Comments
 (0)