Skip to content

fix(printf): %(fmt)T timezone, empty/invalid/nested formats, LC_TIME - #689

Merged
brianjfox merged 1 commit into
mainfrom
fix/printf-time-format
Aug 20, 2026
Merged

fix(printf): %(fmt)T timezone, empty/invalid/nested formats, LC_TIME#689
brianjfox merged 1 commit into
mainfrom
fix/printf-time-format

Conversation

@brianjfox

Copy link
Copy Markdown
Owner

Summary

Fixes #688 — the %(DATEFMT)T branch's six divergences, which were the entire remaining printf.tests diff:

  • TZ: bash's sv_tz hands the shell's exported TZ to libc (setenv + tzset) before every localtime, so export TZ=EST5EDT or unset TZ mid-script takes effect; an unexported TZ assignment deliberately does not (matches bash, verified).
  • empty DATEFMT%X (locale time)
  • a spec that isn't )T warns C': invalid time format specification (NUL byte when the format ran out), prints % literally and rescans the rest as text, exit status unchanged
  • balanced-paren scan: %((%Y))T(1969)
  • the seconds argument is validated like %d's (fooinvalid number, formats 0, exit 1; missing argument still means −1/current time; char-codes work)
  • apply_ctype_locale gains LC_TIME, so LC_ALL=C makes %(%x)T print 05/30/10

Verification

14-case matrix byte-identical vs reference bash 5.3.15 (all TZ scenarios incl. temp-env and unexported, warnings, nested parens, width, validation, format reuse). printf.tests scoreboard 19 → 0 — gnash printf output is now byte-identical to bash across the whole suite (real diff -a zero, unlike the earlier false zero). builtins/errors/varenv/quote/new-exp/heredoc/redir/intl all hold at 0; smoke passes.

Closes #688

🤖 Generated with Claude Code

The %(DATEFMT)T branch diverged from bash in six ways (issue #688),
the entire remaining printf.tests diff:

- TZ: bash's sv_tz hands the shell's EXPORTED TZ to libc (setenv +
  tzset) before every localtime, so `export TZ=EST5EDT' -- or
  `unset TZ' -- mid-script takes effect.  An unexported TZ assignment
  deliberately does NOT (verified against bash).
- an empty DATEFMT formats with %X, the locale's time
- a spec that is not `)T' warns ``C': invalid time format
  specification' (a NUL byte when the format ran out), prints the `%'
  literally and rescans the rest as text, status unchanged
- the closing paren is found by BALANCED scan: `%((%Y))T' -> `(1969)'
- the seconds argument is validated like %d's (getintmax): `foo'
  diagnoses `invalid number' and formats 0, status 1; a missing
  argument still means -1 (current time); '/" char-codes work
- apply_ctype_locale gains LC_TIME, so `LC_ALL=C' makes %(%x)T print
  05/30/10 rather than the startup locale's date format

printf.tests scoreboard 19 -> 0: gnash's printf output is now
byte-identical to bash 5.3.15 across the entire suite (verified with
the diff -a scoreboard; the earlier "0" was the binary-diff false
zero).  builtins/errors/varenv/quote/new-exp/heredoc/redir/intl all
hold at 0.

Closes #688
@brianjfox
brianjfox merged commit c5bcc13 into main Aug 20, 2026
1 check passed
@brianjfox
brianjfox deleted the fix/printf-time-format branch August 20, 2026 08:06
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.

printf: %(fmt)T ignores TZ, empty format, invalid specs, nested parens and bad seconds

1 participant