{"record":{"id":"cc8fa9b3327f570f","repo":"jackwener/OpenCLI","slug":"year-month-day-year-month","errorCode":null,"errorMessage":"日期非法：${year}-${month}-${day}（${year} 年 ${month} 月共 ${maxDay} 天）","messagePattern":"日期非法：(.+?)-(.+?)-(.+?)（(.+?) 年 (.+?) 月共 (.+?) 天）","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/mubu/notes.js","lineNumber":31,"sourceCode":"  return new Date(year, month, 0).getDate();\n}\n\nfunction validateYear(year, label = '年份') {\n  if (!Number.isInteger(year) || year < 1) {\n    throw new ArgumentError(`${label} 非法：${year}，应为正整数`);\n  }\n}\n\nfunction validateMonth(month) {\n  if (!Number.isInteger(month) || month < 1 || month > 12) {\n    throw new ArgumentError(`月份非法：${month}，应为 1-12`);\n  }\n}\n\nfunction validateDay(year, month, day) {\n  const maxDay = lastDayOfMonth(year, month);\n  if (!Number.isInteger(day) || day < 1 || day > maxDay) {\n    throw new ArgumentError(`日期非法：${year}-${month}-${day}（${year} 年 ${month} 月共 ${maxDay} 天）`);\n  }\n}\n\nfunction parseDate(s) {\n  const parts = s.split('-').map(Number);\n  if (parts.length !== 3 || parts.some(isNaN)) {\n    throw new ArgumentError(`日期格式错误：${s}，应为 YYYY-MM-DD`);\n  }\n  const [year, month, day] = parts;\n  validateYear(year);\n  validateMonth(month);\n  validateDay(year, month, day);\n  return { year, month, day };\n}\n\nfunction parseMonth(s) {\n  const parts = s.split('-').map(Number);\n  if (parts.length !== 2 || parts.some(isNaN)) {","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/mubu/notes.js#L13-L49","documentation":"validateDay checks that the day is an integer between 1 and the last day of the given year/month (leap-year aware via lastDayOfMonth). The library throws ArgumentError when the day exceeds the month's length or is otherwise invalid, preventing silently shifted ranges.","triggerScenarios":"parseDate('2023-02-29') (non-leap year), parseDate('2024-04-31') (April has 30 days), or day=0 / non-integer day.","commonSituations":"Users hand-write dates like 02-30, scripts compute day from arithmetic overflow, or assume every month has 31 days.","solutions":["Use a valid day for that month (2024-02-29 is OK, 2023-02-29 is not).","Let a Date object clamp the day: new Date(year, month-1, day) then re-read getDate().","Validate with a calendar check before calling parseDate."],"exampleFix":"// before\nconst d = parseDate('2023-02-29');\n// after\nconst d = parseDate('2024-02-29'); // leap year","handlingStrategy":"validation","validationCode":"function isValidDay(y, m, d) {\n  const max = new Date(y, m, 0).getDate();\n  return Number.isInteger(d) && d >= 1 && d <= max;\n}\nif (!isValidDay(2024, 2, 29)) throw new Error('invalid day for 2024-02');","typeGuard":"const isValidDay = (y, m, d) => {\n  const max = new Date(y, m, 0).getDate();\n  return Number.isInteger(d) && d >= 1 && d <= max;\n};","tryCatchPattern":"try {\n  const d = parseDate(input);\n} catch (e) {\n  if (/日期非法/.test(e.message)) console.error('Day out of range for that month:', e.message);\n  else throw e;\n}","preventionTips":["Build dates from Date objects instead of hand-writing day numbers.","Remember February in non-leap years caps at 28.","Sanity-check ranges with a date library (date-fns, dayjs) before passing them."],"tags":["date-validation","argument-error","cli"],"backgroundTag":"invalid-date-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}