Skip to content

fix(tasks): don't skip a month when a monthly task repeats from the 29th-31st - #3436

Open
TowyTowy wants to merge 1 commit into
go-vikunja:mainfrom
TowyTowy:fix/monthly-repeat-end-of-month
Open

fix(tasks): don't skip a month when a monthly task repeats from the 29th-31st#3436
TowyTowy wants to merge 1 commit into
go-vikunja:mainfrom
TowyTowy:fix/monthly-repeat-end-of-month

Conversation

@TowyTowy

@TowyTowy TowyTowy commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

addOneMonthToDate passes d.Month()+1 with the original day into time.Date, which normalizes an out-of-range day forward rather than clamping it.

A task with repeat mode "Monthly" and a due date of Jan 31 gets a new due date of Mar 3 — February is skipped, and the day of month stays shifted for every occurrence after that (Apr 3, May 3, ...). Same for Mar 31 -> May 1 and May 31 -> Jul 1. It applies to the reminders, start date and end date of the mode too.

This clamps the day to the last day of the target month instead, so Jan 31 repeats to Feb 28 (Feb 29 in a leap year). That matches the "Monthly" label in the UI, and the FREQ=MONTHLY;BYMONTHDAY=<n> rule the CalDAV export already emits for this mode — under RFC 5545 an occurrence can never land in the month after next.

Added a table test for addOneMonthToDate (short month, leap February, 30-day month, year boundary) and an updateDone case for the end-of-month due date. Both fail on main and pass with the fix; the rest of pkg/models is unaffected — no fixture uses repeat_mode: 1.

I'm aware of #3071 replacing this code path for 3.0.0. Filing anyway since the current behaviour ships until then — happy to close it if you'd rather not carry the change.

AI disclosure: written with Claude Code, reviewed and tested before opening.

…9th-31st

addOneMonthToDate passed d.Month()+1 with the original day straight into
time.Date, which normalizes an out-of-range day forward. A task repeating
monthly and due Jan 31 got a new due date of Mar 3: February was skipped
and the day of month stayed shifted for every following occurrence
(Apr 3, May 3, ...). Same for Mar 31 -> May 1, May 31 -> Jul 1.

Clamp the day to the last day of the target month instead, so Jan 31
repeats to Feb 28 (Feb 29 in a leap year). This matches the "Monthly"
label in the UI and the FREQ=MONTHLY;BYMONTHDAY=<n> rule the CalDAV
export already emits for this repeat mode, neither of which allows an
occurrence to land in the month after next.

Co-Authored-By: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added the area/recurring-tasks Repeat rules, recurring task behavior, RRULE label Aug 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/recurring-tasks Repeat rules, recurring task behavior, RRULE

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant