Skip to content

fix(libc): format strftime and asctime as FreeBSD 11 does - #4543

Merged
oneandonlydean merged 1 commit into
boykopovar:mainfrom
coltken95:fix/libc-time
Oct 13, 2026
Merged

oneandonlydean merged 1 commit into
boykopovar:mainfrom
coltken95:fix/libc-time

Conversation

@coltken95

Copy link
Copy Markdown

What

strftime (libc) handed most conversions to the host's strftime, which differs from FreeBSD 11's:

  • E and O with conversions glibc does not pair them with were printed literally (%Ea, %OX, %OD, %OF).
  • Years outside 1000 to 9999: %Y printed 899 and -1 where FreeBSD prints 0899 and -001; %C, %y, %G, %g, %F, %c, %D and %v followed.
  • Out-of-range fields: %I of hour 100 gave 88 (FreeBSD 04), %u of weekday 8 gave 1 (FreeBSD 8), and %W differed.
  • Padding flags on %+ and %v left them unexpanded (%_+ printed literally); on Windows the %-, %_ and %0 flags printed nothing.

asctime printed the year as a plain number; FreeBSD formats it with %Y (0899) and sets years longer than four digits apart ( 12345).

strftime now follows FreeBSD 11 strftime.c with the C locale on both hosts, and asctime follows asctime.c. %s keeps the guest's local-time mktime. The TechnicalDebt entry is rewritten; the Windows gaps it listed are gone, and that the console's libc uses this code is recorded as not measured.

Tested

Linux (Ubuntu 24.04, GCC 13.3). Compared against FreeBSD 11 strftime.c and asctime.c compiled as references: 500000 random cases (every conversion, padding flag, E/O modifier and unknown character, out-of-range fields, years from -2147481748 to 2147485547, short buffers), in UTC and America/New_York; no differences. New guest_strftime test (one case per difference above, short buffer, null format, both asctime layouts); it fails before this change and passes after. All 44 libc guest_* tests registered in this configuration, plus guest_crt and guest_rtc, pass. Windows not built locally (no MinGW toolchain available). No title tested.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed in TechnicalDebt
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • AI-assisted: yes

@oneandonlydean oneandonlydean self-assigned this Oct 12, 2026
@github-actions github-actions Bot mentioned this pull request Oct 12, 2026
6 tasks done
@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 12, 2026
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 12, 2026
@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 13, 2026
@oneandonlydean

Copy link
Copy Markdown
Collaborator

Needs a rebase: docs/dev/debt/libc.md conflicts with the entries merged today (#4733, #4811). The code merges cleanly.

@xXPBSXx

xXPBSXx commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

Tested on Windows 10 (19045), MinGW-w64 GCC 15.2.0 (WinLibs r7), Release: this PR merged onto main ea2bbefb2 (the only merge conflict is docs/dev/debt/libc.md; I took this PR's side for the build).

  • guest_strftime (this PR), guest_time_conversion and guest_mktime pass.
  • As a counter-check I ran a local extra test, not part of this PR, with the padding-flag and modifier cases of FreeBSD 11.4's strftime for 2009-02-07 03:04:05 UTC (single-digit day, hour, minute, second, month, week): %-, %_ and %0 on each of %d %e %H %I %j %k %l %M %m %S %U %W %V, the flag with E / O before and after it (%-Ed, %_Od, %E-e, %O0k), the flag on conversions that ignore it (%-y, %_Y, %0C, %-D, %_T, %0F, %-a, %_b, %0p, %-n, %_t), %_v and %0+. All 9 format strings (about 60 conversions) give the FreeBSD result with this PR.
  • The same cases on main fail: strftime(buf, n, "%-d|%-e|...", &tm) returns 0 with an empty string on Windows, so the Windows part of the description is reproduced and fixed.

Not tested: Linux, a console, a title run.

AI-assisted (Claude Code).

@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 13, 2026
@github-actions github-actions Bot mentioned this pull request Oct 13, 2026
10 tasks done
@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 13, 2026
strftime handed most conversions to the host's strftime, which differs
from FreeBSD 11's for E and O modifiers on conversions glibc does not
pair with them (%Ea was printed literally), padding flags on %+ and %v,
years outside 1000 to 9999 (%Y printed 899 and -1 where FreeBSD prints
0899 and -001), and out-of-range fields (%I of hour 100, %u of weekday
8). On Windows the padding flags printed nothing. strftime now follows
FreeBSD 11 strftime.c with the C locale on every host, and asctime
follows FreeBSD 11 asctime.c, padding years to four digits and setting
longer years apart.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VZWLdTjf1S57iLgn2rcaFb
@coltken95

Copy link
Copy Markdown
Author

Rebased onto 77b9f72. The docs/dev/debt/libc.md conflicts are resolved: #4811's localtime, mktime entry is kept as merged, and this PR's strftime and asctime entry replaces the old strftime one, followed by #4226's wcsftime entry. wcsftime now runs on this strftime; all 51 libc guest_* tests pass on Linux, including guest_strftime and the wcsftime cases.

AI-assisted: yes

@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 13, 2026
@github-actions

github-actions Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.

Pull request Conflicting files (lines on main) Same exports Same new files
#5009 core/libs/prx/libc/src/Time.cpp L237

@oneandonlydean
oneandonlydean merged commit 3ee394e into boykopovar:main Oct 13, 2026
12 checks passed
@coltken95
coltken95 deleted the fix/libc-time branch October 13, 2026 11:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants