{"record":{"id":"e84ef0dce8dc9f52","repo":"jackwener/OpenCLI","slug":"weibo-user-posts-name-must-be-a-valid-calendar","errorCode":null,"errorMessage":"weibo user-posts ${name} must be a valid calendar date","messagePattern":"weibo user-posts (.+?) must be a valid calendar date","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/weibo/user-posts.js","lineNumber":36,"sourceCode":"}\n\nfunction readLimit(raw) {\n    const value = raw === undefined || raw === null || raw === '' ? DEFAULT_LIMIT : Number(raw);\n    if (!Number.isInteger(value) || value < 1 || value > MAX_LIMIT) {\n        throw new ArgumentError(`weibo user-posts limit must be an integer between 1 and ${MAX_LIMIT}`);\n    }\n    return value;\n}\n\nfunction readDate(raw, name) {\n    if (raw === undefined || raw === null || raw === '') return null;\n    const value = String(raw).trim();\n    if (!DATE_RE.test(value)) {\n        throw new ArgumentError(`weibo user-posts ${name} must use YYYY-MM-DD`);\n    }\n    const date = new Date(`${value}T00:00:00+08:00`);\n    if (!Number.isFinite(date.getTime()) || value !== formatShanghaiDate(date)) {\n        throw new ArgumentError(`weibo user-posts ${name} must be a valid calendar date`);\n    }\n    return value;\n}\n\nfunction formatShanghaiDate(date) {\n    const parts = new Intl.DateTimeFormat('en-CA', {\n        timeZone: 'Asia/Shanghai',\n        year: 'numeric',\n        month: '2-digit',\n        day: '2-digit',\n    }).formatToParts(date);\n    const get = (type) => parts.find((part) => part.type === type)?.value;\n    return `${get('year')}-${get('month')}-${get('day')}`;\n}\n\nfunction dateToTimestamp(date) {\n    return Math.floor(new Date(`${date}T00:00:00+08:00`).getTime() / 1000);\n}","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/weibo/user-posts.js#L18-L54","documentation":"After the format check passes, readDate() parses the value as a Shanghai (+08:00) midnight timestamp and round-trips it through formatShanghaiDate. If the parse is non-finite or the round-trip differs from the input (e.g. 2024-02-30), the string was format-valid but not a real calendar date, so this ArgumentError is thrown.","triggerScenarios":"Calling start/end with syntactically valid but nonexistent dates such as '2023-02-29' (non-leap year), '2024-04-31', '2024-13-00', or any value where formatting the parsed date back does not reproduce the input.","commonSituations":"Hand-computed date arithmetic overflowing month ends, template strings like `${year}-02-30`, or dates typed manually with typos in day numbers.","solutions":["Replace with a real calendar date, e.g. '2023-02-28' or '2024-02-29' for a leap year.","Validate the date in your script with a Date round-trip before invoking the command.","If generating ranges programmatically, use date arithmetic instead of string concatenation for the day component."],"exampleFix":"// before\nconst start = `${year}-02-29`; // throws for non-leap 2023\n// after\nconst start = isLeapYear(year) ? `${year}-02-29` : `${year}-02-28`;","handlingStrategy":"validation","validationCode":"function isRealCalendarDate(s) {\n  if (typeof s !== 'string' || !/^\\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()) && d.toISOString().slice(0, 10) === s;\n}\nif (start && !isRealCalendarDate(start)) throw new Error(`not a real date: ${start}`);","typeGuard":"function isCalendarDate(v) {\n  if (typeof v !== 'string') return false;\n  const [y, m, d] = v.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":null,"preventionTips":["Round-trip generated dates through Date before use.","Never construct day components by adding to strings; use date arithmetic.","Watch February 29 handling in leap years."],"tags":["argument-validation","calendar-date","cli"],"backgroundTag":"invalid-date-format","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}