Skip to content

date: Fix %x, %X, %r to respect locale settings#11068

Open
abendrothj wants to merge 4 commits intouutils:mainfrom
abendrothj:fix/dateformat
Open

date: Fix %x, %X, %r to respect locale settings#11068
abendrothj wants to merge 4 commits intouutils:mainfrom
abendrothj:fix/dateformat

Conversation

@abendrothj
Copy link
Contributor

Fixes #10284

Previously these format specifiers were hardcoded to US/POSIX defaults, ignoring LC_TIME and LC_ALL. Now they call nl_langinfo to get the locale's actual format strings.

Changes:

  • Add D_FMT, T_FMT, T_FMT_AMPM query functions in locale.rs
  • Expand %x/%X/%r before jiff formatting in date.rs
  • Un-ignore and extend locale tests in test_date.rs

now for ci...

@oech3
Copy link
Contributor

oech3 commented Feb 23, 2026

Please cargo fmt

@abendrothj abendrothj force-pushed the fix/dateformat branch 2 times, most recently from 462cb08 to 032b444 Compare February 23, 2026 09:30
@abendrothj
Copy link
Contributor Author

Please cargo fmt

oops, forgot prehook doesnt work on mac currently

@abendrothj abendrothj force-pushed the fix/dateformat branch 2 times, most recently from aa1ee97 to 0146bba Compare February 23, 2026 09:36
- Add locale.rs functions to query nl_langinfo for D_FMT, T_FMT, T_FMT_AMPM
- Add expand_locale_specifiers() to replace %x, %X, %r with locale formats
- Integrate locale specifier expansion before jiff formatting
- Un-ignore and extend locale tests with graceful degradation
@github-actions
Copy link

GNU testsuite comparison:

Skipping an intermittent issue tests/pr/bounded-memory (passes in this run but fails in the 'main' branch)

@abendrothj abendrothj requested a review from cakebaker February 25, 2026 07:47
@github-actions
Copy link

GNU testsuite comparison:

Skipping an intermittent issue tests/tail/follow-name (passes in this run but fails in the 'main' branch)
Note: The gnu test tests/expand/bounded-memory is now being skipped but was previously passing.

Comment on lines 1788 to 1799
.stdout_is("19/01/1997\n");
.stdout_is("19.01.1997\n");
Copy link
Contributor

@cakebaker cakebaker Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the new assert is incorrect (it fails on my machine) and the original assert was correct.

Here is the output I get from GNU date:

$ TZ=UTC LC_ALL=fr_FR.UTF-8 date -d "1997-01-19 08:17:48" "+%x"
19/01/1997

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be all inline to GNU now

Comment on lines +1815 to +1826
if !locale_is_available("fr_FR.UTF-8") {
println!("Skipping French locale %X test — fr_FR.UTF-8 not available");
return;
}
new_ucmd!()
.env("TZ", "UTC")
.env("LC_ALL", "fr_FR.UTF-8")
.arg("-d")
.arg("1997-01-19 08:17:48")
.arg("+%X")
.succeeds()
.stdout_is("08:17:48\n");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would use a locale with a different time format like en_US.UTF-8, for which the output should be 08:17:48 AM.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sorry, my bad. I meant to use en_US.UTF-8 here in test_date_format_big_x_locale_aware (and not in test_date_format_r_locale_aware) because the expected outputs for the C and fr_FR.UTF-8 locales are identical.

@github-actions
Copy link

GNU testsuite comparison:

Congrats! The gnu test tests/csplit/csplit-heap is now passing!

@github-actions
Copy link

GNU testsuite comparison:

GNU test failed: tests/date/resolution. tests/date/resolution is passing on 'main'. Maybe you have to rebase?
Skipping an intermittent issue tests/date/date-locale-hour (passes in this run but fails in the 'main' branch)
Congrats! The gnu test tests/csplit/csplit-heap is now passing!

@codspeed-hq
Copy link

codspeed-hq bot commented Feb 25, 2026

Merging this PR will not alter performance

✅ 294 untouched benchmarks
⏩ 42 skipped benchmarks1


Comparing abendrothj:fix/dateformat (9a5b0e9) with main (9ac174b)

Open in CodSpeed

Footnotes

  1. 42 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@github-actions
Copy link

GNU testsuite comparison:

Skip an intermittent issue tests/pr/bounded-memory (fails in this run but passes in the 'main' branch)
Congrats! The gnu test tests/csplit/csplit-heap is now passing!

@abendrothj abendrothj requested a review from cakebaker February 25, 2026 12:05
Comment on lines +1873 to +1880
new_ucmd!()
.env("TZ", "UTC")
.env("LC_ALL", "fr_FR.UTF-8")
.arg("-d")
.arg("1997-01-19 08:17:48")
.arg("+%r")
.succeeds()
.stdout_is(expected);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While the test looks good, it fails on Linux because the implementation doesn't output the expected value.

Here is the output of the program:

$ TZ=UTC LC_ALL=fr_FR.UTF-8 cargo run -q date -d "1997-01-19 08:17:48" "+%r"
08:17:48 AM

And here is the expected output from GNU date:

$ TZ=UTC LC_ALL=fr_FR.UTF-8 date -d "1997-01-19 08:17:48" "+%r"
08:17:48

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

date - %x format specifier ignores locale settings

4 participants