diff --git a/src/uu/date/src/format_modifiers.rs b/src/uu/date/src/format_modifiers.rs index 35e1d8d9982..2e456570ada 100644 --- a/src/uu/date/src/format_modifiers.rs +++ b/src/uu/date/src/format_modifiers.rs @@ -236,7 +236,25 @@ fn format_with_modifiers( let formatted = broken_down.to_string_with_config(config, &base_format)?; if !parsed.flags.is_empty() || parsed.width.is_some() { - let modified = apply_modifiers(&formatted, &parsed)?; + // Strip `-` from composite specifiers (D, F, T, etc.) so + // apply_modifiers does not remove inner leading zeros. + let effective = + if is_composite_specifier(parsed.spec) && parsed.flags.contains('-') { + ParsedSpec { + flags: &parsed.flags.replace('-', ""), + width: parsed.width, + spec: parsed.spec, + len: parsed.len, + } + } else { + ParsedSpec { + flags: parsed.flags, + width: parsed.width, + spec: parsed.spec, + len: parsed.len, + } + }; + let modified = apply_modifiers(&formatted, &effective)?; result.push_str(&modified); } else { result.push_str(&formatted); @@ -256,6 +274,13 @@ fn format_with_modifiers( Ok(result) } +/// Returns true if the specifier is composite (multi-field, e.g. %D = %m/%d/%y). +fn is_composite_specifier(spec: &str) -> bool { + // strip leading colons (e.g. ":z" → "z") + let s = spec.trim_start_matches(':'); + matches!(s, "D" | "F" | "T" | "r" | "R" | "c" | "x" | "X") +} + /// Returns true if the specifier produces text output (default pad is space) /// rather than numeric output (default pad is zero). fn is_text_specifier(specifier: &str) -> bool { diff --git a/tests/by-util/test_date.rs b/tests/by-util/test_date.rs index bc3a249764e..be29191474b 100644 --- a/tests/by-util/test_date.rs +++ b/tests/by-util/test_date.rs @@ -3148,3 +3148,27 @@ fn test_nanoseconds_width_prefix_ignored_issue12001() { // compare to 4 because of \n assert_eq!(result.stdout().len(), 4); } + +// Regression test for https://github.com/uutils/coreutils/issues/11657 +// strftime flags like `-` should not propagate into composite specifiers like %D +#[test] +fn test_date_format_composite_specifier_flags_issue11657() { + // GNU date treats %D as atomic — the `-` flag should NOT strip leading + // zeros from the month/day within the expansion of %D. + new_ucmd!() + .env("TZ", "UTC") + .arg("-d") + .arg("2024-06-15") + .arg("+%-D") + .succeeds() + .stdout_is("06/15/24\n"); + + // Same for %F (ISO date) + new_ucmd!() + .env("TZ", "UTC") + .arg("-d") + .arg("2024-01-05") + .arg("+%-F") + .succeeds() + .stdout_is("2024-01-05\n"); +}