{"record":{"id":"8ab4e23def0f1081","repo":"can1357/oh-my-pi","slug":"dates-before-1970-are-unsupported","errorCode":null,"errorMessage":"dates before 1970 are unsupported","messagePattern":"dates before 1970 are unsupported","errorType":"validation","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"crates/pi-builtins/src/fd.rs","lineNumber":1406,"sourceCode":"\tlet hour = parse_u32_part(time_parts.next(), \"hour\")?;\n\tlet minute = parse_u32_part(time_parts.next(), \"minute\")?;\n\tlet second = parse_u32_part(time_parts.next(), \"second\")?;\n\tif time_parts.next().is_some()\n\t\t|| !(1..=12).contains(&month)\n\t\t|| !(1..=31).contains(&day)\n\t\t|| hour > 23\n\t\t|| minute > 59\n\t\t|| second > 59\n\t{\n\t\treturn Err(io::Error::new(io::ErrorKind::InvalidInput, format!(\"invalid date: {value}\")));\n\t}\n\tlet days = days_from_civil(year, month, day);\n\tlet seconds = days\n\t\t.checked_mul(86_400)\n\t\t.and_then(|base| base.checked_add(i64::from(hour * 3_600 + minute * 60 + second)))\n\t\t.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, \"date is out of range\"))?;\n\tif seconds < 0 {\n\t\treturn Err(io::Error::new(io::ErrorKind::InvalidInput, \"dates before 1970 are unsupported\"));\n\t}\n\tOk(UNIX_EPOCH + Duration::from_secs(u64::try_from(seconds).unwrap_or(u64::MAX)))\n}\n\nfn parse_i32_part(value: Option<&str>, name: &str) -> io::Result<i32> {\n\tvalue\n\t\t.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, format!(\"missing {name}\")))?\n\t\t.parse::<i32>()\n\t\t.map_err(|err| io::Error::new(io::ErrorKind::InvalidInput, err.to_string()))\n}\n\nfn parse_u32_part(value: Option<&str>, name: &str) -> io::Result<u32> {\n\tvalue\n\t\t.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, format!(\"missing {name}\")))?\n\t\t.parse::<u32>()\n\t\t.map_err(|err| io::Error::new(io::ErrorKind::InvalidInput, err.to_string()))\n}\n","sourceCodeStart":1388,"sourceCodeEnd":1424,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/crates/pi-builtins/src/fd.rs#L1388-L1424","documentation":"The fd builtin's date parser converts a parsed civil date/time into a SystemTime by computing seconds since the UNIX epoch. If the computed seconds value is negative (i.e., the parsed timestamp predates 1970-01-01T00:00:00Z), the conversion cannot produce a valid epoch-based SystemTime, so an InvalidInput io::Error with this message is returned.","triggerScenarios":"Calling the in-process fd builtin with a date filter (e.g. --newer or similar timestamp option) whose parsed year/month/day/hour/minute/second components resolve to a timestamp before the UNIX epoch, such as '1969-12-31' or an explicitly negative date string.","commonSituations":"Users referencing archival files with pre-1970 timestamps; scripts that pass '--newer 1970-01-01' minus one second; locales or fixtures containing historic dates; a typo like '1697' instead of '1997' in a date argument.","solutions":["Use a date on or after 1970-01-01T00:00:00 in the date argument","If you need pre-epoch filtering, implement the comparison outside the builtin using file metadata directly","Double-check the date string for typos (year digits swapped or truncated)"],"exampleFix":"// before\nfd --newer '1969-12-31 23:59' .\n// after\nfd --newer '1970-01-01 00:00' .","handlingStrategy":"validation","validationCode":"fn validate_epoch_date(date: &str) -> Result<(), String> {\n\t// crude pre-check: reject years before 1970 before invoking the builtin\n\tlet year: i32 = date.split('-').next().unwrap_or(\"\").parse().map_err(|_| \"bad year\")?;\n\tif year < 1970 {\n\t\treturn Err(format!(\"year {year} is before 1970; unsupported\"));\n\t}\n\tOk(())\n}","typeGuard":null,"tryCatchPattern":"match builtin_result {\n\tErr(e) if e.to_string().contains(\"dates before 1970\") => eprintln!(\"adjust date to >= 1970: {e}\"),\n\tErr(e) => return Err(e),\n\tOk(v) => /* ... */,\n}","preventionTips":["Always generate date filter arguments from date/time formatters constrained to >= 1970","Validate user-supplied date strings with a parser before passing them to the builtin","Watch for typos in years (4-digit sanity check)"],"tags":["rust","io","date-parsing","input-validation"],"backgroundTag":"date-before-epoch-unsupported","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}