From 4c2227b9bb261ac7cd17defdba1a91f5d5c9ab11 Mon Sep 17 00:00:00 2001 From: Devel Date: Wed, 16 Sep 2026 19:09:03 +0300 Subject: [PATCH] date: add support for dot-separated dates --- src/uu/date/src/date.rs | 39 ++++++++++++++++++++++++++++++++------ tests/by-util/test_date.rs | 5 +++++ 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/src/uu/date/src/date.rs b/src/uu/date/src/date.rs index 455e72d6e09..8fcfc830ea3 100644 --- a/src/uu/date/src/date.rs +++ b/src/uu/date/src/date.rs @@ -1176,6 +1176,32 @@ fn parse_dates_from_reader( })) } +/// Convert a date string to iso if it is seperated by dots. +fn convert_to_iso(date_str: &str) -> Option { + // Seperate the date from anything else, in case we have something like "01.01.2008 03:00 p.m." + let mut parts = date_str.splitn(2, ' '); + let date_part = parts.next()?; + let time_part = parts.next(); + + // Get the year, month and the day + let date_subparts: Vec<&str> = date_part.split('.').collect(); + if date_subparts.len() != 3 { + return None; + } + + // Format in iso style + let new_date = format!( + "{}-{}-{}", + date_subparts[2], date_subparts[1], date_subparts[0] + ); + + // Concat the date and the time back + match time_part { + Some(time) => Some(format!("{new_date} {time}")), + None => Some(new_date), + } +} + /// Parse a string into either an in-range [`Zoned`] value or an extended date. fn parse_date>( s: S, @@ -1209,7 +1235,9 @@ fn parse_date>( return Ok(ParsedDateTime::InRange(zoned)); } - match parse_datetime::parse_datetime_at_date(now.clone(), input_str) { + let input_str = convert_to_iso(input_str).unwrap_or(input_str.to_string()); + + match parse_datetime::parse_datetime_at_date(now.clone(), &input_str) { // Convert to system timezone for display // (parse_datetime returns a value in the input's timezone) Ok(ParsedDateTime::InRange(date)) => { @@ -1248,11 +1276,10 @@ fn parse_date>( Ok(ParsedDateTime::InRange(result)) } Ok(ParsedDateTime::Extended(date)) if allow_extended => Ok(ParsedDateTime::Extended(date)), - Ok(ParsedDateTime::Extended(_)) => Err(( - input_str.into(), - parse_datetime::ParseDateTimeError::InvalidInput, - )), - Err(e) => Err((input_str.into(), e)), + Ok(ParsedDateTime::Extended(_)) => { + Err((input_str, parse_datetime::ParseDateTimeError::InvalidInput)) + } + Err(e) => Err((input_str, e)), } } diff --git a/tests/by-util/test_date.rs b/tests/by-util/test_date.rs index 67c3b8d5257..406308f2d45 100644 --- a/tests/by-util/test_date.rs +++ b/tests/by-util/test_date.rs @@ -3297,3 +3297,8 @@ fn test_write_error() { .fails_with_code(1) .stderr_is("date: write error: No space left on device\n"); } + +#[test] +fn test_date_separated_by_dots() { + new_ucmd!().args(&["-d", "15.06.2004 3:00 a.m."]).succeeds(); +}