Proposal: Add a test case for an off-by-one error at quarter boundaries

Hi everyone!

While mentoring this exercise and revisiting my own solution, I found a bug that isn’t caught by the current test suite: quarter-based deliveries incorrectly roll over to the next year even when the start date is still inside the target quarter — specifically, when the start date falls in the target quarter’s own last month (March for Q1, June for Q2, September for Q3, December for Q4).

Why this is worth a test

This is a classic off-by-one/fencepost bug, and it’s easy to introduce in more than one way. In my own solution, it came from an inclusive comparison (start.month >= des * 3 instead of >) that swept the boundary month into the wrong branch. Looking at community solutions, I found a second, differently-shaped implementation that hit the exact same boundary via a different mechanism — a quarter-from-month formula that assumed 0-indexed months (month // 3 + 1 instead of (month - 1) // 3 + 1), which also misclassifies exactly the last month of each quarter.

Two independently-written solutions, using unrelated logic, made the same mistake at the same boundary — and both passed all 16 existing canonical tests. That’s because none of the three current quarter tests start in the last month of the quarter being requested:

  • Q1 test starts in January (Q1’s first month)
  • Q4 test starts in April (unrelated quarter)
  • Q3 test starts in October (unrelated quarter)

None of them exercise “am I still inside the target quarter” at the one point where that logic is actually hard to get right.

Suggested test

{
    "uuid": "to-be-defined",
    "description": "Q2 starting in the last month of the second quarter translates to the last workday of the second quarter of this year",
    "property": "deliveryDate",
    "input": {
        "meetingStart": "2019-06-15T09:30:00",
        "description": "Q2"
    },
    "expected": "2019-06-28T08:00:00"
}

Happy to adjust the description string or pick a different date if there’s a preference for consistency with the existing test names. Is this worth adding to the canonical data?

+1

Hopefully they never have a planning meeting after the last workday, or after 8:00 on the last workday.

"Q<N>" Before or in N-th quarter - At 8:00 on the last workday of this year’s N-th quarter

+1 from me, too.

+1 from me.

That’s three maintainers on board with the change. Please do proceed with a problem spec PR!

1 Like

Took me a moment to realize what you’re hinting at — nicely spotted. If I get you right, the issue is specifically when the meeting start falls on the last workday of the quarter itself, after 8 a.m. Strictly following the current logic, the delivery date would end up earlier than the meeting start, e.g.:

  • meetingStart: 2026-06-30T09:30:00
  • expected deliveryDate (per current logic): 2026-06-30T08:00:00

That’s a delivery date in the “past” relative to the meeting that triggered it — which doesn’t really make sense.

If I’ve understood correctly, I think this is worth treating as a separate topic from my original proposal. Before I draft a test case, though — should this roll over to the next quarter’s last workday, or is the exercise meant to leave this behavior undefined/out of scope? Happy to write up a test either way once we’re aligned on the expected behavior.

I don’t think we need to draft a test case for that, I’d consider it out of scope.

1 Like

Thanks for the green light! I’ve opened the PR here: swift-scheduling: add test for quarterly rollover off-by-one error by Konovor · Pull Request #2669 · exercism/problem-specifications · GitHub

1 Like