Skip to content

Fix monthly weekly task appearing as due every day (#1266)#1368

Open
zazer0 wants to merge 1 commit intoHabitRPG:developfrom
zazer0:fix/monthly-daily-alwaysdue
Open

Fix monthly weekly task appearing as due every day (#1266)#1368
zazer0 wants to merge 1 commit intoHabitRPG:developfrom
zazer0:fix/monthly-daily-alwaysdue

Conversation

@zazer0
Copy link

@zazer0 zazer0 commented Nov 16, 2025

Summary

Fixes #1266 where daily tasks set to repeat monthly on a specific weekday occurrence (e.g., "3rd Tuesday of every month") were incorrectly appearing as due every day instead of just once per month.

Root Cause

The bug was in TaskFormView.swift line 1049 (now line 1063). The code was using Calendar.component(.weekOfMonth, from: startDate) - 1 which:

  1. Uses .weekOfMonth that returns which week of the month a date is in (1-6), not which occurrence of a specific weekday
  2. Subtracts 1 to convert to 0-indexed values
  3. Produces incorrect values, especially problematic when the month starts on the target weekday (resulting in 1 - 1 = 0, which is invalid)

Example of the bug:

  • User selects January 1, 2025 (first Wednesday of the month)
  • Old code: weekOfMonth(1) - 1 = 0 ❌ (invalid, causes server to miscalculate and show task as due every day)
  • New code: weekdayOrdinal = 1 ✅ (correctly indicates 1st occurrence)

Solution

Use DateFormatter pattern "F" to get the weekday ordinal (1-5) which correctly represents which occurrence of that specific weekday it is in the month. This matches what the Habitica server expects in the weeksOfMonth array.

Changes

  • Added Calendar.weekdayOrdinal(for:) extension method that uses DateFormatter pattern "F"
  • Fixed line 1063 to use Calendar.current.weekdayOrdinal(for: startDate) instead of the buggy calculation

Testing

  • Swift syntax validation passes
  • Code follows the existing pattern used in TaskRepeatablesSummaryInteractor.swift which already uses DateFormatter pattern "FEEEE" for display
  • Existing test TaskRepeatablesSummaryInteractorTests.swift:163-164 expects weeksOfMonth = [5] for "5 Tuesday", confirming server expects 1-indexed values (1-5)

Habitica User ID

@zazy0

Fixes issue HabitRPG#1266 where daily tasks set to repeat monthly on a specific
weekday occurrence (e.g., "3rd Tuesday of every month") were incorrectly
appearing as due every day instead of just once per month.

Root cause: The code was using Calendar.component(.weekOfMonth) which
returns which week of the month a date is in (1-6), then subtracting 1.
This produced incorrect values, especially when the month starts on the
target weekday (resulting in 1 - 1 = 0, which is invalid).

Solution: Use DateFormatter pattern "F" to get the weekday ordinal (1-5)
which correctly represents which occurrence of that specific weekday it
is in the month. This matches what the server expects in the weeksOfMonth
array.

Changes:
- Added Calendar.weekdayOrdinal(for:) extension method
- Fixed line 1063 to use weekdayOrdinal instead of weekOfMonth-1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

daily set to repeat monthly resetting to "due" every day

1 participant