{"record":{"id":"3658789e2110e06c","repo":"sansan0/TrendRadar","slug":"stripped","errorCode":null,"errorMessage":"日期格式错误: {stripped}","messagePattern":"日期格式错误: (.+?)","errorType":"validation","errorClass":"InvalidParameterError","httpStatus":null,"severity":"error","filePath":"mcp_server/utils/validators.py","lineNumber":402,"sourceCode":"    if isinstance(date_range, str):\n        stripped = date_range.strip()\n\n        # 1. 检查是否是 JSON 对象格式\n        if stripped.startswith('{') and stripped.endswith('}'):\n            try:\n                date_range = json.loads(stripped)\n            except json.JSONDecodeError as e:\n                raise InvalidParameterError(\n                    f\"date_range JSON 解析失败: {e}\",\n                    suggestion='请使用正确的JSON格式: {\"start\": \"YYYY-MM-DD\", \"end\": \"YYYY-MM-DD\"}'\n                )\n        # 2. 检查是否是单日字符串格式 YYYY-MM-DD\n        elif len(stripped) == 10 and stripped[4] == '-' and stripped[7] == '-':\n            try:\n                single_date = datetime.strptime(stripped, \"%Y-%m-%d\")\n                return (single_date, single_date)\n            except ValueError:\n                raise InvalidParameterError(\n                    f\"日期格式错误: {stripped}\",\n                    suggestion=\"请使用 YYYY-MM-DD 格式，例如: 2025-10-11\"\n                )\n        # 3. 尝试自然语言解析\n        else:\n            try:\n                result = DateParser.resolve_date_range_expression(stripped)\n                if result.get(\"success\"):\n                    dr = result[\"date_range\"]\n                    start_date = datetime.strptime(dr[\"start\"], \"%Y-%m-%d\")\n                    end_date = datetime.strptime(dr[\"end\"], \"%Y-%m-%d\")\n                    return (start_date, end_date)\n                else:\n                    raise InvalidParameterError(\n                        f\"无法识别的日期表达式: {stripped}\",\n                        suggestion=\"支持格式: YYYY-MM-DD, {\\\"start\\\": \\\"...\\\", \\\"end\\\": \\\"...\\\"}, 或自然语言（今天、本周、最近7天等）\"\n                    )\n            except InvalidParameterError:","sourceCodeStart":384,"sourceCodeEnd":420,"githubUrl":"https://github.com/sansan0/TrendRadar/blob/8ee26026ba6c11dec41a95fb3895a7162876caa1/mcp_server/utils/validators.py#L384-L420","documentation":"Raised by normalize_date_range when the input is a 10-character string with dashes at positions 4 and 7 (shaped like YYYY-MM-DD) but strptime rejects it — i.e. syntactically date-shaped but not a real calendar date. Examples: 2025-13-01 (month 13), 2025-02-30, 2025-00-10, 2025-10-32.","triggerScenarios":"Passing date_range: \"2025-02-30\" (Feb 30), \"2025-13-01\" (month 13), or \"abcd-ef-gh\" (10 chars, dashes in place, non-numeric). The pre-check only inspects length and dash positions, so content errors surface here via strptime ValueError.","commonSituations":"LLM arithmetic on dates producing impossible days (Feb 29 on non-leap years like 2025-02-29); month/day transposition creating month>12; hand-typed dates; template strings with placeholder junk.","solutions":["Use a real calendar date; check leap years for Feb 29 (2024 yes, 2025 no)","Compute dates with date libraries (Python datetime/dateutil, JS date-fns) instead of string arithmetic","Validate client-side with a regex plus calendar check (e.g. new Date(s) round-trip) before sending","If you need a range, send the {\"start\", \"end\"} object rather than a single-day string"],"exampleFix":"// before\n{\"date_range\": \"2025-02-30\"}\n// after\n{\"date_range\": \"2025-02-28\"}","handlingStrategy":"validation","validationCode":"function isRealDate(s: string): boolean {\n  if (!/^\\d{4}-\\d{2}-\\d{2}$/.test(s)) return false;\n  const [y, m, d] = s.split('-').map(Number);\n  const dt = new Date(Date.UTC(y, m - 1, d));\n  return dt.getUTCFullYear() === y && dt.getUTCMonth() === m - 1 && dt.getUTCDate() === d;\n}\nif (!isRealDate(dateRange)) throw new Error('invalid calendar date');","typeGuard":"const isCalendarDate = (s: string): boolean => {\n  const [y, m, d] = s.split('-').map(Number);\n  const dt = new Date(Date.UTC(y, m - 1, d));\n  return dt.getUTCFullYear() === y && dt.getUTCMonth() === m - 1 && dt.getUTCDate() === d;\n};","tryCatchPattern":"try { call({ date_range: s }); }\ncatch (e) {\n  if (/日期格式错误/.test(e.message)) call({ date_range: iso(new Date(s)) });\n  else throw e;\n}","preventionTips":["Generate dates with datetime/date-fns, never string math","Round-trip check: new Date(s) must reproduce the same y/m/d","Beware Feb 29 on non-leap years in LLM-computed dates"],"tags":["date","calendar","validation"],"backgroundTag":null,"analyzedSha":"8ee26026ba6c11dec41a95fb3895a7162876caa1","analyzedAt":"2026-08-15T01:42:18.084Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}