From 188aa8e99b45b272d9ed4b0618a09817a924f43f Mon Sep 17 00:00:00 2001 From: naoNao89 Date: Sun, 15 Feb 2026 01:55:09 +0000 Subject: [PATCH] date: fix double periods in Hungarian month abbreviations 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 --- 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 df29bccf0c3..88816d9daed 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 ffbb4a2bea9..b9a3c9f8712 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() {