can1357/oh-my-pi · error · io::Error

invalid date: {value}

Error message

invalid date: {value}

What it means

`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.

Source

Thrown at crates/pi-builtins/src/fd.rs:1385

		"h" | "hr" | "hrs" | "hour" | "hours" => count.saturating_mul(60 * 60),
		"d" | "day" | "days" => count.saturating_mul(24 * 60 * 60),
		"w" | "week" | "weeks" => count.saturating_mul(7 * 24 * 60 * 60),
		_ => return Ok(None),
	};
	Ok(Some(Duration::from_secs(seconds)))
}

fn parse_utc_datetime(value: &str) -> io::Result<SystemTime> {
	let (date, time) = value
		.trim()
		.split_once(' ')
		.unwrap_or_else(|| (value.trim(), "00:00:00"));
	let mut date_parts = date.split('-');
	let year = parse_i32_part(date_parts.next(), "year")?;
	let month = parse_u32_part(date_parts.next(), "month")?;
	let day = parse_u32_part(date_parts.next(), "day")?;
	if date_parts.next().is_some() {
		return Err(io::Error::new(io::ErrorKind::InvalidInput, format!("invalid date: {value}")));
	}
	let mut time_parts = time.split(':');
	let hour = parse_u32_part(time_parts.next(), "hour")?;
	let minute = parse_u32_part(time_parts.next(), "minute")?;
	let second = parse_u32_part(time_parts.next(), "second")?;
	if time_parts.next().is_some()
		|| !(1..=12).contains(&month)
		|| !(1..=31).contains(&day)
		|| hour > 23
		|| minute > 59
		|| second > 59
	{
		return Err(io::Error::new(io::ErrorKind::InvalidInput, format!("invalid date: {value}")));
	}
	let days = days_from_civil(year, month, day);
	let seconds = days
		.checked_mul(86_400)
		.and_then(|base| base.checked_add(i64::from(hour * 3_600 + minute * 60 + second)))

View on GitHub (pinned to 9690622007)

Solutions

  1. 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`.
  2. Remove timezone-offset suffixes; the parser has no timezone support — convert to UTC first.
  3. 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.
  4. For epoch input, use the `@<seconds>` form instead of a calendar date.

Example fix

// before (extra hyphenated segment from ISO offset)
find --changed 2024-01-15T10:30:00-05:00
// after (UTC, space-separated)
find --changed 2024-01-15 15:30:00
Defensive patterns

Strategy: validation

Validate before calling

fn validate_utc_date(value: &str) -> Result<(), String> {
    let trimmed = value.trim();
    let (date, time) = trimmed
        .split_once(' ')
        .unwrap_or((trimmed, "00:00:00"));
    let parts: Vec<&str> = date.split('-').collect();
    if parts.len() != 3 {
        return Err(format!("expected exactly YYYY-MM-DD, got '{date}'"));
    }
    parts.iter().all(|p| !p.is_empty() && p.bytes().all(|b| b.is_ascii_digit()))
        .then_some(())
        .ok_or_else(|| format!("non-numeric date component in '{value}'"))
}

Type guard

fn is_supported_utc_datetime(value: &str) -> bool {
    let (date, _) = value.trim().split_once(' ').unwrap_or((value.trim(), ""));
    let parts: Vec<&str> = date.split('-').collect();
    parts.len() == 3
        && parts.iter().all(|p| !p.is_empty() && p.bytes().all(|b| b.is_ascii_digit()))
}

Try / catch

match parse_time_filter(input) {
    Ok(time) => use_time(time),
    Err(e) if e.to_string().starts_with("invalid date") => {
        eprintln!("'{input}' is not YYYY-MM-DD [HH:MM:SS] (UTC); convert timezones and strip ISO-8601 suffixes first");
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: 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`.

Common situations: 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.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/a8444e3fe183bdf9. Report an issue: GitHub.