{"record":{"id":"109fa5bcffab9cdd","repo":"HKUDS/Vibe-Trading","slug":"quarter-value-r-is-not-a-calendar-quarter-end-u","errorCode":null,"errorMessage":"quarter {value!r} is not a calendar quarter end; use 03-31, 06-30, 09-30 or 12-31","messagePattern":"quarter (.+?) is not a calendar quarter end; use 03-31, 06-30, 09-30 or 12-31","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/tools/institutional_holdings_tool.py","lineNumber":361,"sourceCode":"\n    Raises:\n        ValueError: When the text is not a recognizable quarter, the year is\n            outside ``1993..current+1``, or the date is not a quarter end.\n    \"\"\"\n    text = str(value).strip().upper().replace(\" \", \"\")\n    match = re.fullmatch(r\"(\\d{4})-?Q([1-4])\", text)\n    if match:\n        year, quarter = int(match.group(1)), int(match.group(2))\n    else:\n        match = re.fullmatch(r\"(\\d{4})-(\\d{1,2})-(\\d{1,2})\", text)\n        if not match:\n            raise ValueError(\n                f\"quarter {value!r} is not recognizable; use '2026Q1' or a quarter-end date '2026-03-31'\"\n            )\n        year, month, day = (int(g) for g in match.groups())\n        quarter = next((q for q, md in _QUARTER_ENDS.items() if md == (month, day)), None)\n        if quarter is None:\n            raise ValueError(\n                f\"quarter {value!r} is not a calendar quarter end; use 03-31, 06-30, 09-30 or 12-31\"\n            )\n    if not _MIN_QUARTER_YEAR <= year <= date.today().year + 1:\n        raise ValueError(f\"quarter year {year} is outside {_MIN_QUARTER_YEAR}..{date.today().year + 1}\")\n    month, day = _QUARTER_ENDS[quarter]\n    return f\"{year:04d}-{month:02d}-{day:02d}\"\n\n\ndef _quarter_label(period_end: Optional[str]) -> Optional[str]:\n    \"\"\"Render a ``YYYY-MM-DD`` quarter end as ``YYYYQn``, or ``None`` if unusable.\"\"\"\n    if not period_end or len(str(period_end)) < 7:\n        return None\n    text = str(period_end)\n    try:\n        year, month = int(text[:4]), int(text[5:7])\n    except ValueError:\n        return None\n    quarter = next((q for q, md in _QUARTER_ENDS.items() if md[0] == month), None)","sourceCodeStart":343,"sourceCodeEnd":379,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/tools/institutional_holdings_tool.py#L343-L379","documentation":"When a YYYY-MM-DD form is supplied, the (month, day) must exactly match one of the calendar quarter ends (03-31, 06-30, 09-30, 12-31). Any other date — even a valid one like 2026-03-30 — is rejected because the API needs true quarter ends.","triggerScenarios":"quarter='2026-04-01', '2026-03-30', or a fiscal quarter end that is not a calendar quarter end.","commonSituations":"Companies with non-calendar fiscal years; users rounding the quarter boundary; timezone/off-by-one date math.","solutions":["Use the exact quarter-end dates: 03-31, 06-30, 09-30, 12-31","Prefer the 'YYYYQn' shorthand which avoids date math entirely","Snap dates to quarter ends programmatically before calling"],"exampleFix":"# before\nexecute(quarter=\"2026-04-01\")\n# after\nexecute(quarter=\"2026Q1\")  # or \"2026-03-31\"","handlingStrategy":"validation","validationCode":"from datetime import date\nQUARTER_ENDS = {3:(3,31),6:(6,30),9:(9,30),12:(12,31)}\nd = date.fromisoformat(q)\nassert (d.month, d.day) in QUARTER_ENDS.values(), f\"{q} is not a quarter end\"","typeGuard":"def is_calendar_quarter_end(q: str) -> bool:\n    from datetime import date\n    try:\n        d = date.fromisoformat(q)\n    except ValueError:\n        return False\n    return (d.month, d.day) in {(3,31),(6,30),(9,30),(12,31)}","tryCatchPattern":"try:\n    qn = _parse_quarter(q)\nexcept ValueError as e:\n    if \"not a calendar quarter end\" in str(e):\n        qn = _parse_quarter(f\"{d.year}Q{(d.month-1)//3+1}\")\n    else:\n        raise","preventionTips":["Use YYYYQn shorthand","Snap dates to quarter ends programmatically","Remember fiscal != calendar quarters here"],"tags":["python","date-parsing","validation"],"backgroundTag":"invalid-date-format","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}