Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/uucore/src/lib/features/i18n/datetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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);
Expand Down
25 changes: 24 additions & 1 deletion tests/by-util/test_date.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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() {
Expand Down
Loading