{"record":{"id":"a8444e3fe183bdf9","repo":"can1357/oh-my-pi","slug":"invalid-date-value","errorCode":null,"errorMessage":"invalid date: {value}","messagePattern":"invalid date: (.+?)","errorType":"validation","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"crates/pi-builtins/src/fd.rs","lineNumber":1385,"sourceCode":"\t\t\"h\" | \"hr\" | \"hrs\" | \"hour\" | \"hours\" => count.saturating_mul(60 * 60),\n\t\t\"d\" | \"day\" | \"days\" => count.saturating_mul(24 * 60 * 60),\n\t\t\"w\" | \"week\" | \"weeks\" => count.saturating_mul(7 * 24 * 60 * 60),\n\t\t_ => return Ok(None),\n\t};\n\tOk(Some(Duration::from_secs(seconds)))\n}\n\nfn parse_utc_datetime(value: &str) -> io::Result<SystemTime> {\n\tlet (date, time) = value\n\t\t.trim()\n\t\t.split_once(' ')\n\t\t.unwrap_or_else(|| (value.trim(), \"00:00:00\"));\n\tlet mut date_parts = date.split('-');\n\tlet year = parse_i32_part(date_parts.next(), \"year\")?;\n\tlet month = parse_u32_part(date_parts.next(), \"month\")?;\n\tlet day = parse_u32_part(date_parts.next(), \"day\")?;\n\tif date_parts.next().is_some() {\n\t\treturn Err(io::Error::new(io::ErrorKind::InvalidInput, format!(\"invalid date: {value}\")));\n\t}\n\tlet mut time_parts = time.split(':');\n\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)))","sourceCodeStart":1367,"sourceCodeEnd":1403,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/crates/pi-builtins/src/fd.rs#L1367-L1403","documentation":"`parse_utc_datetime` rejects the date string with `invalid date: {value}` when the `YYYY-MM-DD` portion splits into more than three `-`-separated parts. After consuming year, month, and day, any leftover component (a fourth part) means the format isn't a supported calendar date, so the library returns `InvalidInput`. It's a strict format check: exactly `year-month-day` is expected.","triggerScenarios":"Passing a date with extra hyphen-separated segments, e.g. `2024-01-15-05` or an ISO-8601 datetime with `T`/timezone encoded via hyphens like `2024-01-15T10:30:00Z` only if it contains extra `-` fields (e.g. `2024-01-15-10:30`); also values like `2024-01-15-extra`.","commonSituations":"Using an ISO 8601 timestamp containing timezone-offset hyphens (e.g. `2024-01-15T10:30:00-05:00`) — the `-05:00` lands in the date section; passing `YYYY-MM-DD` output from tools that append a suffix; mixing the datetime space-separated form (`2024-01-15 10:30:00`) with a `T` separator plus offset.","solutions":["Use exactly `YYYY-MM-DD` (optionally followed by a space and `HH:MM:SS`) in UTC: `2024-01-15` or `2024-01-15 10:30:00`.","Remove timezone-offset suffixes; the parser has no timezone support — convert to UTC first.","If you have a `T`-separated ISO string like `2024-01-15T10:30:00Z`, rewrite it as `2024-01-15 10:30:00` before passing it.","For epoch input, use the `@<seconds>` form instead of a calendar date."],"exampleFix":"// before (extra hyphenated segment from ISO offset)\nfind --changed 2024-01-15T10:30:00-05:00\n// after (UTC, space-separated)\nfind --changed 2024-01-15 15:30:00","handlingStrategy":"validation","validationCode":"fn validate_utc_date(value: &str) -> Result<(), String> {\n    let trimmed = value.trim();\n    let (date, time) = trimmed\n        .split_once(' ')\n        .unwrap_or((trimmed, \"00:00:00\"));\n    let parts: Vec<&str> = date.split('-').collect();\n    if parts.len() != 3 {\n        return Err(format!(\"expected exactly YYYY-MM-DD, got '{date}'\"));\n    }\n    parts.iter().all(|p| !p.is_empty() && p.bytes().all(|b| b.is_ascii_digit()))\n        .then_some(())\n        .ok_or_else(|| format!(\"non-numeric date component in '{value}'\"))\n}","typeGuard":"fn is_supported_utc_datetime(value: &str) -> bool {\n    let (date, _) = value.trim().split_once(' ').unwrap_or((value.trim(), \"\"));\n    let parts: Vec<&str> = date.split('-').collect();\n    parts.len() == 3\n        && parts.iter().all(|p| !p.is_empty() && p.bytes().all(|b| b.is_ascii_digit()))\n}","tryCatchPattern":"match parse_time_filter(input) {\n    Ok(time) => use_time(time),\n    Err(e) if e.to_string().starts_with(\"invalid date\") => {\n        eprintln!(\"'{input}' is not YYYY-MM-DD [HH:MM:SS] (UTC); convert timezones and strip ISO-8601 suffixes first\");\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Always convert to UTC and strip timezone offsets before passing a datetime string.","Rewrite `T`-separated ISO-8601 timestamps to the space-separated form the parser expects.","Regex-check user input: `^\\d{4}-\\d{2}-\\d{2}( \\d{2}:\\d{2}:\\d{2})?$`.","Prefer `@<epoch-seconds>` for programmatically sourced timestamps."],"tags":["input-validation","date-parsing","rust","invalid-input"],"backgroundTag":"invalid-date-format","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}