{"record":{"id":"2752bdaf8aaed9a3","repo":"jackwener/OpenCLI","slug":"raw","errorCode":null,"errorMessage":"无法解析定时时间: ${raw}","messagePattern":"无法解析定时时间: (.+?)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/wechat-channels/publish.js","lineNumber":96,"sourceCode":"  }\n  return resolved;\n}\n\nfunction parseTimeoutSeconds(raw) {\n  const timeout = raw == null || raw === '' ? 600 : Number(raw);\n  if (!Number.isInteger(timeout) || timeout < 30) {\n    throw new ArgumentError('--timeout must be an integer >= 30 seconds');\n  }\n  return timeout;\n}\n\nfunction parseScheduleDate(raw) {\n  if (!raw) return null;\n  const dt = typeof raw === 'number'\n    ? new Date(raw < 1e12 ? raw * 1000 : raw)\n    : new Date(String(raw));\n  if (Number.isNaN(dt.getTime())) {\n    throw new ArgumentError(`无法解析定时时间: ${raw}`);\n  }\n  if (dt.getTime() <= Date.now()) {\n    throw new ArgumentError('定时时间必须晚于当前时间');\n  }\n  return dt;\n}\n\nfunction parseBooleanFlag(raw) {\n  return raw === true || raw === 'true' || raw === '1' || raw === 1;\n}\n\nfunction remainingMs(deadline, label) {\n  const left = deadline - Date.now();\n  if (left <= 0) {\n    throw new CommandExecutionError(`${label}超时，请增加 --timeout 后重试`);\n  }\n  return left;\n}","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/wechat-channels/publish.js#L78-L114","documentation":"parseScheduleDate accepts epoch seconds/milliseconds (number) or a date string and throws ArgumentError when new Date(...) yields NaN — i.e. the value cannot be parsed as any recognizable date. The schedule time must be parseable before it is checked for being in the future.","triggerScenarios":"Passing --schedule 'tomorrow 5pm' (locale phrases), a malformed string like '2026/13/40 25:00', or an arbitrary non-date string.","commonSituations":"Human-readable relative dates, timezone-suffixed strings the JS Date parser rejects, shell quoting stripping characters, mixing DD/MM vs MM/DD expectations.","solutions":["Use an unambiguous format such as ISO 8601: --schedule '2026-09-01T10:00:00+08:00'.","Pass an epoch timestamp (seconds or milliseconds) as a number.","Pre-compute the timestamp: date -d 'tomorrow 10:00' +%s then pass that value."],"exampleFix":"// before\nnode publish.js --schedule \"tomorrow at 10am\"\n// after\nnode publish.js --schedule \"2026-08-30T10:00:00+08:00\"","handlingStrategy":"validation","validationCode":"const dt = new Date(scheduleRaw);\nif (Number.isNaN(dt.getTime())) {\n  throw new Error(`Unparseable schedule time: ${scheduleRaw}; use ISO 8601 or epoch`);\n}","typeGuard":"function isParseableDate(v) {\n  return !Number.isNaN(new Date(typeof v === 'number' ? v : String(v)).getTime());\n}","tryCatchPattern":"try {\n  await publish({ schedule: scheduleRaw });\n} catch (e) {\n  if (/无法解析定时时间/.test(e.message)) {\n    console.error('Use ISO 8601 like 2026-09-01T10:00:00+08:00');\n  }\n  throw e;\n}","preventionTips":["Always use ISO 8601 strings with explicit timezone offsets.","Prefer epoch timestamps generated with date +%s in shell wrappers.","Avoid human-relative phrases like 'tomorrow 5pm'."],"tags":["cli","argument-validation","date-parsing"],"backgroundTag":"invalid-date-format","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}