From bca02e45f223e5a3b0cb0fd9e1c7b5682095adcb Mon Sep 17 00:00:00 2001 From: yuankunzhang Date: Sat, 9 Aug 2025 22:18:56 +0800 Subject: [PATCH] date: consolidate date parsing logic Removed the `parse_offset` function and rely on `parse_date` only. --- src/uu/date/src/date.rs | 54 +++++++++-------------------------------- 1 file changed, 11 insertions(+), 43 deletions(-) diff --git a/src/uu/date/src/date.rs b/src/uu/date/src/date.rs index ea76a631e..19e0a8712 100644 --- a/src/uu/date/src/date.rs +++ b/src/uu/date/src/date.rs @@ -8,7 +8,7 @@ use clap::{Arg, ArgAction, Command}; use jiff::fmt::strtime; use jiff::tz::TimeZone; -use jiff::{SignedDuration, Timestamp, Zoned}; +use jiff::{Timestamp, Zoned}; #[cfg(all(unix, not(target_os = "macos"), not(target_os = "redox")))] use libc::{CLOCK_REALTIME, clock_settime, timespec}; use std::fs::File; @@ -64,10 +64,9 @@ enum Format { /// Various places that dates can come from enum DateSource { Now, - Custom(String), File(PathBuf), Stdin, - Human(SignedDuration), + Human(String), } enum Iso8601Format { @@ -141,11 +140,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { }; let date_source = if let Some(date) = matches.get_one::(OPT_DATE) { - if let Ok(duration) = parse_offset(date.as_str()) { - DateSource::Human(duration) - } else { - DateSource::Custom(date.into()) - } + DateSource::Human(date.into()) } else if let Some(file) = matches.get_one::(OPT_FILE) { match file.as_ref() { "-" => DateSource::Stdin, @@ -176,7 +171,9 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { if let Some(date) = settings.set_to { // All set time functions expect UTC datetimes. let date = if settings.utc { - date.with_time_zone(TimeZone::UTC) + date.datetime().to_zoned(TimeZone::UTC).map_err(|e| { + USimpleError::new(1, translate!("date-error-invalid-date", "error" => e)) + })? } else { date }; @@ -193,27 +190,11 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { // Iterate over all dates - whether it's a single date or a file. let dates: Box> = match settings.date_source { - DateSource::Custom(ref input) => { + DateSource::Human(ref input) => { let date = parse_date(input); let iter = std::iter::once(date); Box::new(iter) } - DateSource::Human(relative_time) => { - // Double check the result is overflow or not of the current_time + relative_time - // it may cause a panic of chrono::datetime::DateTime add - match now.checked_add(relative_time) { - Ok(date) => { - let iter = std::iter::once(Ok(date)); - Box::new(iter) - } - Err(_) => { - return Err(USimpleError::new( - 1, - translate!("date-error-date-overflow", "date" => relative_time), - )); - } - } - } DateSource::Stdin => { let lines = BufReader::new(std::io::stdin()).lines(); let iter = lines.map_while(Result::ok).map(parse_date); @@ -391,28 +372,15 @@ fn parse_date + Clone>( Ok(date) => { let timestamp = Timestamp::new(date.timestamp(), date.timestamp_subsec_nanos() as i32).unwrap(); - Ok(Zoned::new(timestamp, TimeZone::UTC)) + Ok(Zoned::new( + timestamp, + TimeZone::try_system().unwrap_or(TimeZone::UTC), + )) } Err(e) => Err((s.as_ref().into(), e)), } } -// TODO: Convert `parse_datetime` to jiff and remove wrapper from chrono to jiff structures. -// Also, consider whether parse_datetime::parse_datetime_at_date can be renamed to something -// like parse_datetime::parse_offset, instead of doing some addition/subtraction. -fn parse_offset(date: &str) -> Result { - let ref_time = chrono::Local::now(); - if let Ok(new_time) = parse_datetime::parse_datetime_at_date(ref_time, date) { - let duration = new_time.signed_duration_since(ref_time); - Ok(SignedDuration::new( - duration.num_seconds(), - duration.subsec_nanos(), - )) - } else { - Err(()) - } -} - #[cfg(not(any(unix, windows)))] fn set_system_datetime(_date: Zoned) -> UResult<()> { unimplemented!("setting date not implemented (unsupported target)");