{"record":{"id":"9ec7e3f0b488bfa1","repo":"jackwener/OpenCLI","slug":"from-to-9ec7e3","errorCode":null,"errorMessage":"--from 不能晚于 --to","messagePattern":"--from 不能晚于 --to","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/mubu/notes.js","lineNumber":75,"sourceCode":"\nfunction dateToKey(d) {\n  return `${d.year}-${String(d.month).padStart(2, '0')}-${String(d.day).padStart(2, '0')}`;\n}\n\n/** 将各种时间参数统一解析为 {start, end} */\nfunction resolveRange(kwargs) {\n  const dateStr = kwargs.date;\n  const monthStr = kwargs.month;\n  const yearArg = kwargs.year;\n  const fromStr = kwargs.from;\n  const toStr = kwargs.to;\n\n  // --from / --to 优先级最高\n  if (fromStr || toStr) {\n    if (!fromStr) throw new ArgumentError('使用 --to 时必须同时指定 --from');\n    const start = parseDate(fromStr);\n    const end = toStr ? parseDate(toStr) : localToday();\n    if (dateToKey(start) > dateToKey(end)) throw new ArgumentError('--from 不能晚于 --to');\n    return { start, end };\n  }\n\n  if (yearArg !== undefined && yearArg !== null) {\n    validateYear(yearArg, '--year');\n    return {\n      start: { year: yearArg, month: 1, day: 1 },\n      end: { year: yearArg, month: 12, day: 31 },\n    };\n  }\n\n  if (monthStr) {\n    const { year, month } = parseMonth(monthStr);\n    return {\n      start: { year, month, day: 1 },\n      end: { year, month, day: lastDayOfMonth(year, month) },\n    };\n  }","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/mubu/notes.js#L57-L93","documentation":"After parsing both --from and --to, resolveRange compares their date keys and rejects an inverted range where the start date is after the end date, since that would produce an empty/nonsensical export.","triggerScenarios":"Running with --from 2024-06-01 --to 2024-01-01, or when --to defaults to localToday while --from is in the future (clock skew / wrong system date).","commonSituations":"Copy-paste swapped dates, timezone differences making 'today' earlier than the user's local date, or scripts generating ranges with swapped variables.","solutions":["Swap the values so --from <= --to.","If --to defaults to today, check the machine's date/timezone (system clock may be wrong).","Clamp in code: if (from > to) [from, to] = [to, from] before calling."],"exampleFix":"// before\nawait notes({ from: '2024-06-01', to: '2024-01-01' });\n// after\nawait notes({ from: '2024-01-01', to: '2024-06-01' });","handlingStrategy":"validation","validationCode":"const key = (d) => d.replace(/-/g, '');\nif (key(from) > key(to)) throw new Error('--from must not be later than --to');","typeGuard":"const isOrderedRange = (from, to) => from.replace(/-/g, '') <= to.replace(/-/g, '');","tryCatchPattern":"try {\n  await notes({ from, to });\n} catch (e) {\n  if (e.message.includes('--from 不能晚于 --to')) {\n    [from, to] = [to, from]; // or report to user\n  } else throw e;\n}","preventionTips":["Check the system clock/timezone if dates are computed at runtime.","Normalize and compare date strings before calling the command.","Keep range endpoints derived from one source (same 'now') to avoid skew."],"tags":["argument-error","cli","date-range"],"backgroundTag":"invalid-date-range","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}