mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-06-16 17:55:26 -04:00
fix: monthly tasks scheduled for day 29-31 skip every short month (#1668)
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
"""compute_next_run monthly must clamp to short months, not skip them.
|
||||
|
||||
Old behavior: now.replace(day=31) raises ValueError in February, the
|
||||
except set candidate = now, candidate <= now then jumped straight to the
|
||||
NEXT month (which does clamp). A task scheduled for day 31 therefore never
|
||||
fired in February, April, June, September or November.
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
import pytest
|
||||
|
||||
from src.task_scheduler import compute_next_run
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"day,after,expected",
|
||||
[
|
||||
(31, datetime(2026, 2, 15, 12, 0), datetime(2026, 2, 28, 9, 0)),
|
||||
(30, datetime(2026, 2, 1, 12, 0), datetime(2026, 2, 28, 9, 0)),
|
||||
(29, datetime(2026, 2, 1, 12, 0), datetime(2026, 2, 28, 9, 0)),
|
||||
(29, datetime(2028, 2, 1, 12, 0), datetime(2028, 2, 29, 9, 0)),
|
||||
(31, datetime(2026, 4, 1, 12, 0), datetime(2026, 4, 30, 9, 0)),
|
||||
],
|
||||
)
|
||||
def test_monthly_clamps_to_last_day_of_current_short_month(day, after, expected):
|
||||
out = compute_next_run("monthly", "09:00", scheduled_day=day, after=after)
|
||||
assert out == expected
|
||||
|
||||
|
||||
def test_monthly_clamped_slot_already_passed_rolls_to_next_month():
|
||||
out = compute_next_run(
|
||||
"monthly", "09:00", scheduled_day=31, after=datetime(2026, 2, 28, 10, 0)
|
||||
)
|
||||
assert out == datetime(2026, 3, 31, 9, 0)
|
||||
|
||||
|
||||
def test_monthly_regular_day_still_fires_this_month():
|
||||
out = compute_next_run(
|
||||
"monthly", "09:00", scheduled_day=15, after=datetime(2026, 6, 10, 12, 0)
|
||||
)
|
||||
assert out == datetime(2026, 6, 15, 9, 0)
|
||||
|
||||
|
||||
def test_monthly_regular_day_passed_rolls_to_next_month():
|
||||
out = compute_next_run(
|
||||
"monthly", "09:00", scheduled_day=15, after=datetime(2026, 6, 20, 12, 0)
|
||||
)
|
||||
assert out == datetime(2026, 7, 15, 9, 0)
|
||||
|
||||
|
||||
def test_monthly_december_year_rollover():
|
||||
out = compute_next_run(
|
||||
"monthly", "09:00", scheduled_day=31, after=datetime(2026, 12, 31, 10, 0)
|
||||
)
|
||||
assert out == datetime(2027, 1, 31, 9, 0)
|
||||
Reference in New Issue
Block a user