{"record":{"id":"ed84f463d11139b5","repo":"sansan0/TrendRadar","slug":"date-str","errorCode":null,"errorMessage":"日期格式错误: {date_str}","messagePattern":"日期格式错误: (.+?)","errorType":"validation","errorClass":"InvalidParameterError","httpStatus":null,"severity":"error","filePath":"mcp_server/utils/validators.py","lineNumber":310,"sourceCode":"\n\ndef validate_date(date_str: str) -> datetime:\n    \"\"\"\n    验证日期格式\n\n    Args:\n        date_str: 日期字符串 (YYYY-MM-DD)\n\n    Returns:\n        datetime对象\n\n    Raises:\n        InvalidParameterError: 日期格式错误\n    \"\"\"\n    try:\n        return datetime.strptime(date_str, \"%Y-%m-%d\")\n    except ValueError:\n        raise InvalidParameterError(\n            f\"日期格式错误: {date_str}\",\n            suggestion=\"请使用 YYYY-MM-DD 格式，例如: 2025-10-11\"\n        )\n\n\ndef normalize_date_range(date_range: Optional[Union[dict, str]]) -> Optional[Union[dict, str]]:\n    \"\"\"\n    规范化 date_range 参数\n\n    某些 MCP 客户端（特别是 HTTP 方式）会将 JSON 对象序列化为字符串传入。\n    此函数尝试将 JSON 字符串解析为 dict，如果不是 JSON 格式则保持原样。\n\n    Args:\n        date_range: 日期范围，可能是:\n            - dict: {\"start\": \"2025-01-01\", \"end\": \"2025-01-07\"}\n            - JSON 字符串: '{\"start\": \"2025-01-01\", \"end\": \"2025-01-07\"}'\n            - 普通字符串: \"今天\", \"昨天\", \"2025-01-01\"\n            - None","sourceCodeStart":292,"sourceCodeEnd":328,"githubUrl":"https://github.com/sansan0/TrendRadar/blob/8ee26026ba6c11dec41a95fb3895a7162876caa1/mcp_server/utils/validators.py#L292-L328","documentation":"Raised by validate_date when datetime.strptime(date_str, \"%Y-%m-%d\") fails. Only the exact ISO form is accepted: 4-digit year, dash, 2-digit month, dash, 2-digit day. Common failures include slashes (2025/10/11), single-digit parts (2025-9-1), timestamps (2025-10-11T00:00), or invalid calendar dates (2025-02-30).","triggerScenarios":"Passing start/end inside date_range, or any date-typed parameter, in a non-ISO format: \"2025.10.11\", \"11-10-2025\", \"2025-10-11 00:00:00\", \"2025-1-01\". Zero-padded ISO only.","commonSituations":"Locale-specific date habits (US mm-dd-yyyy, dots in Europe); frontend date pickers emitting full ISO 8601 timestamps; LLM-generated dates without zero-padding; Excel-exported dates with slashes.","solutions":["Use exact YYYY-MM-DD with zero-padded parts: 2025-10-11","Client-side, format with a library before sending: date.toISOString().slice(0, 10) (JS) or strftime('%Y-%m-%d') (Python)","Strip time components before sending; the validator does not accept timestamps","Wrap calls in try/except InvalidParameterError and re-format/retry once"],"exampleFix":"// before\n{\"date_range\": {\"start\": \"2025/10/01\", \"end\": \"2025-10-11\"}}\n// after\n{\"date_range\": {\"start\": \"2025-10-01\", \"end\": \"2025-10-11\"}}","handlingStrategy":"validation","validationCode":"const iso = (d: Date) => d.toISOString().slice(0, 10);\nif (!/^\\d{4}-\\d{2}-\\d{2}$/.test(dateStr)) dateStr = iso(new Date(dateStr));","typeGuard":"const isIsoDate = (s: string): boolean => {\n  if (!/^\\d{4}-\\d{2}-\\d{2}$/.test(s)) return false;\n  const d = new Date(s + 'T00:00:00Z');\n  return !Number.isNaN(d.getTime());\n};","tryCatchPattern":"try { call({ date_range: dr }); }\ncatch (e) {\n  if (/日期格式错误/.test(e.message)) call({ date_range: { start: iso(new Date(dr.start)), end: iso(new Date(dr.end)) } });\n  else throw e;\n}","preventionTips":["Always format dates through a date library to YYYY-MM-DD before sending","Slice off time components: toISOString().slice(0, 10)","Reject non-zero-padded user input client-side"],"tags":["date","format","validation","iso8601"],"backgroundTag":null,"analyzedSha":"8ee26026ba6c11dec41a95fb3895a7162876caa1","analyzedAt":"2026-08-15T01:42:18.084Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}