Skip to content

date: expand %c with the locale's date and time format - #14791

Open
Ascol57 wants to merge 1 commit into
uutils:mainfrom
Ascol57:date-c-locale-datetime-format
Open

Ascol57 wants to merge 1 commit into
uutils:mainfrom
Ascol57:date-c-locale-datetime-format

Conversation

@Ascol57

@Ascol57 Ascol57 commented Sep 21, 2026

Copy link
Copy Markdown

Fixes #14679

%c came out with the POSIX format whatever the locale said, because jiff's
PosixCustom renders it that way and nothing overrode it. GNU date stands
%c for the locale's D_T_FMT, so under en_US.UTF-8 it should carry a
12-hour clock and the timezone.

$ TZ=UTC LC_ALL=en_US.UTF-8 date -d 2023-11-14T23:13:20 +%c
  before: Tue Nov 14 23:13:20 2023
  after:  Tue 14 Nov 2023 11:13:20 PM UTC
  GNU:    Tue 14 Nov 2023 11:13:20 PM UTC

A note on the issue title

The issue reads date -u +%c and blames -u. -u is in fact respected — the
hours differ correctly with and without it. What the reporter saw was the
missing UTC at the end, which comes from %c ignoring the locale, so that is
what this fixes. Under LC_ALL=C the two agreed all along, since the C
locale's D_T_FMT is the POSIX format.

How

locale.rs already queried nl_langinfo for the default format, so this adds
a D_T_FMT accessor beside it and factors the shared setlocale/nl_langinfo
block into query_nl_langinfo.

date.rs expands %c in the format string rather than rendering it directly.
That keeps the expansion on the normal path, so the month and day names it
contains still go through the existing ICU localization, and the specifiers
inside it still reach jiff. %%c stays a literal, as it must.

A locale whose D_T_FMT is not valid UTF-8 (legacy charsets such as
zh_TW.euctw) leaves %c alone rather than forcing a lossy conversion.

Platforms

Gated on the same glibc-Linux cfg as the existing _DATE_FMT query, so
nothing changes elsewhere. D_T_FMT is POSIX, unlike the _DATE_FMT
extension, so the other Unix platforms could be wired up as a follow-up by
someone able to test them.

Testing

Three tests: the en_US.UTF-8 one asserts +%c renders exactly like
+"$(locale d_t_fmt)", which is the GNU contract and avoids pinning one
distribution's locale data; the other two cover the C locale and %%c.
Neutralizing the expansion makes the first fail with
left: "Tue Nov 14 23:13:20 2023" against
right: "Tue 14 Nov 2023 11:13:20 PM UTC" — the symptom from the issue — while
the other two stay green.

Also swept %c %x %X %r %D %T %F %s %N %Z %z %j %U %G, plus x%cy and
%%c%c, against GNU 9.7 under C and en_US.UTF-8: only %x and %X still
differ, which is #11068's territory, untouched here.

Left alone

jiff renders %c with the POSIX format, so it came out the same whatever
the locale said. GNU date stands %c for the locale's D_T_FMT, which under
en_US.UTF-8 means a 12-hour clock and a timezone.

Query D_T_FMT beside the existing _DATE_FMT lookup, and expand %c in the
format string rather than rendering it directly, so the month and day
names it contains still go through the existing ICU localization.

Fixes uutils#14679
Copilot AI lite review requested due to automatic review settings September 21, 2026 18:21

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Copilot review overview

Review effort: Lite
Findings: 1 Medium severity

Open (1)
What changed in this PR

This PR makes date +%c use the locale’s D_T_FMT format on supported Linux systems, matching GNU date.

Changes:

  • Adds a cached D_T_FMT query through nl_langinfo.
  • Expands bare %c into the locale format before normal date formatting.
  • Adds tests for locale-specific %c, the C locale, and escaped %%c.
File Description
tests/​by-util/​test_date.rs Adds coverage for locale-based %c expansion and escaping.
src/​uu/​date/​src/​locale.rs Queries and caches the locale’s D_T_FMT value.
src/​uu/​date/​src/​date.rs Substitutes %c with D_T_FMT before formatting.

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

/// data, and it is exactly the property that was broken: `%c` used to fall
/// back to the POSIX format whatever the locale said.
#[test]
#[cfg(unix)]
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.

bug(date): date does not respect -u when +%c

2 participants