From 72c782fbfdcd8d6c7d60cf0d337c3e4c994bd2c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=E1=BA=A3=20th=E1=BA=BF=20gi=E1=BB=9Bi=20l=C3=A0=20Rust?= <90588855+naoNao89@users.noreply.github.com> Date: Sun, 15 Feb 2026 19:15:29 +0700 Subject: [PATCH] date: fix double periods in Hungarian month abbreviations (#10945) ICU's DateTimeFormatter with fieldsets::M::medium() returns month abbreviations with trailing periods (e.g., "febr." for Hungarian). When the Hungarian locale format string contains "%Y. %b. %d" (with periods after year and month), the ICU output resulted in double periods: "febr.." This fix strips trailing periods from ICU month abbreviations to match the standard C/POSIX locale behavior. Also adds a new test case for abbreviated month names across multiple locales to prevent regression. Fixes #10921 Co-authored-by: naoNao89 --- src/uucore/src/lib/features/i18n/datetime.rs | 8 ++++++- tests/by-util/test_date.rs | 25 +++++++++++++++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/uucore/src/lib/features/i18n/datetime.rs b/src/uucore/src/lib/features/i18n/datetime.rs index df29bccf0..88816d9da 100644 --- a/src/uucore/src/lib/features/i18n/datetime.rs +++ b/src/uucore/src/lib/features/i18n/datetime.rs @@ -3,7 +3,7 @@ // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. -// spell-checker:ignore fieldsets prefs +// spell-checker:ignore fieldsets prefs febr //! Locale-aware datetime formatting utilities using ICU and jiff-icu @@ -111,7 +111,13 @@ pub fn localize_format_string(format: &str, date: JiffDate) -> String { } if fmt.contains("%b") || fmt.contains("%h") { if let Ok(f) = DateTimeFormatter::try_new(locale_prefs, fieldsets::M::medium()) { + // ICU's medium format may include trailing periods (e.g., "febr." for Hungarian), + // which when combined with locale format strings that also add periods after + // %b (e.g., "%Y. %b. %d") results in double periods ("febr.."). + // The standard C/POSIX locale via nl_langinfo returns abbreviations + // WITHOUT trailing periods, so we strip them here for consistency. let month_abbrev = f.format(&iso_date).to_string(); + let month_abbrev = month_abbrev.trim_end_matches('.').to_string(); fmt = fmt .replace("%b", &month_abbrev) .replace("%h", &month_abbrev); diff --git a/tests/by-util/test_date.rs b/tests/by-util/test_date.rs index ffbb4a2be..b9a3c9f87 100644 --- a/tests/by-util/test_date.rs +++ b/tests/by-util/test_date.rs @@ -3,7 +3,7 @@ // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. // -// spell-checker: ignore: AEDT AEST EEST NZDT NZST Kolkata Iseconds févr février janv janvier mercredi samedi sommes juin décembre Januar Juni Dezember enero junio diciembre gennaio giugno dicembre junho dezembro lundi dimanche Montag Sonntag Samstag sábado +// spell-checker: ignore: AEDT AEST EEST NZDT NZST Kolkata Iseconds févr février janv janvier mercredi samedi sommes juin décembre Januar Juni Dezember enero junio diciembre gennaio giugno dicembre junho dezembro lundi dimanche Montag Sonntag Samstag sábado febr use std::cmp::Ordering; @@ -2056,6 +2056,29 @@ fn test_locale_month_names() { } } +#[test] +#[cfg(unix)] +fn test_locale_abbreviated_month_names() { + // %b abbreviated month names: Feb, Jun, Dec for each locale + // This test ensures we don't get double periods in locales like Hungarian + // where ICU returns "febr." but the format string also adds a period after %b + for (loc, feb, jun, dec) in [ + ("fr_FR.UTF-8", "févr", "juin", "déc"), + ("de_DE.UTF-8", "Feb", "Jun", "Dez"), + ("es_ES.UTF-8", "feb", "jun", "dic"), + ("it_IT.UTF-8", "feb", "giu", "dic"), + ("pt_BR.UTF-8", "fev", "jun", "dez"), + ("ja_JP.UTF-8", "2月", "6月", "12月"), + ("zh_CN.UTF-8", "2月", "6月", "12月"), + // Hungarian locale - the fix ensures no double periods + ("hu_HU.UTF-8", "febr", "jún", "dec"), + ] { + check_date(loc, "2026-02-12", "+%b", feb); + check_date(loc, "2026-06-14", "+%b", jun); + check_date(loc, "2026-12-09", "+%b", dec); + } +} + #[test] #[cfg(unix)] fn test_locale_day_names() {