diff --git a/src/uu/date/locales/en-US.ftl b/src/uu/date/locales/en-US.ftl index 72113c405..b320cefef 100644 --- a/src/uu/date/locales/en-US.ftl +++ b/src/uu/date/locales/en-US.ftl @@ -104,3 +104,4 @@ date-error-date-overflow = date overflow '{$date}' date-error-setting-date-not-supported-macos = setting the date is not supported by macOS date-error-setting-date-not-supported-redox = setting the date is not supported by Redox date-error-cannot-set-date = cannot set date +date-error-extra-operand = extra operand '{$operand}' diff --git a/src/uu/date/locales/fr-FR.ftl b/src/uu/date/locales/fr-FR.ftl index 204121f92..2529b4263 100644 --- a/src/uu/date/locales/fr-FR.ftl +++ b/src/uu/date/locales/fr-FR.ftl @@ -99,3 +99,4 @@ date-error-date-overflow = débordement de date '{$date}' date-error-setting-date-not-supported-macos = la définition de la date n'est pas prise en charge par macOS date-error-setting-date-not-supported-redox = la définition de la date n'est pas prise en charge par Redox date-error-cannot-set-date = impossible de définir la date +date-error-extra-operand = opérande supplémentaire '{$operand}' diff --git a/src/uu/date/src/date.rs b/src/uu/date/src/date.rs index 4a5c583cf..145583f9e 100644 --- a/src/uu/date/src/date.rs +++ b/src/uu/date/src/date.rs @@ -169,7 +169,28 @@ fn parse_military_timezone_with_offset(s: &str) -> Option { #[uucore::main] #[allow(clippy::cognitive_complexity)] pub fn uumain(args: impl uucore::Args) -> UResult<()> { - let matches = uucore::clap_localization::handle_clap_result(uu_app(), args)?; + let args: Vec = args.collect(); + let matches = match uu_app().try_get_matches_from(&args) { + Ok(matches) => matches, + Err(e) => { + match e.kind() { + clap::error::ErrorKind::DisplayHelp | clap::error::ErrorKind::DisplayVersion => { + return Err(e.into()); + } + _ => { + // Convert unknown options to be treated as invalid date format + // This ensures consistent exit status 1 instead of clap's exit status 77 + if let Some(arg) = args.get(1) { + return Err(USimpleError::new( + 1, + translate!("date-error-invalid-date", "date" => arg.to_string_lossy()), + )); + } + return Err(USimpleError::new(1, e.to_string())); + } + } + } + }; // Check for extra operands (multiple positional arguments) if let Some(formats) = matches.get_many::(OPT_FORMAT) { @@ -526,7 +547,7 @@ pub fn uu_app() -> Command { .help(translate!("date-help-universal")) .action(ArgAction::SetTrue), ) - .arg(Arg::new(OPT_FORMAT).num_args(0..)) + .arg(Arg::new(OPT_FORMAT).num_args(0..).trailing_var_arg(true)) } /// Return the appropriate format string for the given settings. diff --git a/tests/by-util/test_date.rs b/tests/by-util/test_date.rs index 33fb2e0e5..689211bf9 100644 --- a/tests/by-util/test_date.rs +++ b/tests/by-util/test_date.rs @@ -32,6 +32,30 @@ fn test_extra_operands() { .stderr_contains("extra operand 'extra'"); } +#[test] +fn test_invalid_long_option() { + new_ucmd!() + .arg("--fB") + .fails_with_code(1) + .stderr_contains("invalid date '--fB'"); +} + +#[test] +fn test_invalid_short_option() { + new_ucmd!() + .arg("-w") + .fails_with_code(1) + .stderr_contains("invalid date '-w'"); +} + +#[test] +fn test_single_dash_as_date() { + new_ucmd!() + .arg("-") + .fails_with_code(1) + .stderr_contains("invalid date"); +} + #[test] fn test_date_email() { for param in ["--rfc-email", "--rfc-e", "-R", "--rfc-2822", "--rfc-822"] {