Skip to content

locale.nl_langinfo(): decode LC_TIME items from glibc wide locale data #152905

Closed

Description

@serhiy-storchaka

locale.nl_langinfo() returns the LC_TIME text items — month and day names, the date/time formats, AM/PM strings, alternative digits — decoded with the current LC_CTYPE encoding (PyUnicode_DecodeLocale). This has two drawbacks.

First, it only works if the LC_TIME encoding has a matching Python codec. If a locale's data is in an encoding Python cannot decode, the call fails or returns mojibake, even though the information is available from the C library.

Second, to make the decoding correct when LC_TIME and LC_CTYPE differ, the implementation temporarily switches the global LC_CTYPE locale (see the change_locale() path, added in gh-133740). That global change affects other threads and is the kind of thread-unsafe setlocale() use tracked in gh-127081.

glibc already stores every LC_TIME text item a second time in wide form, exposed through the _NL_W* constants (_NL_WMON_1, _NL_WDAY_1, _NL_WD_T_FMT, _NL_WALT_DIGITS, …). nl_langinfo() returns these as a wchar_t*, i.e. as Unicode code points independent of the locale byte encoding. Reading them needs neither a Python codec nor a temporary LC_CTYPE change.

Proposal: on glibc, map each narrow LC_TIME constant to its wide counterpart and decode the result with PyUnicode_FromWideChar(). The observable result is unchanged for locales that already round-trip today; it becomes correct (and thread-safe) for the cases above.

Scope / notes:

  • glibc-only. The _NL_W* symbols are glibc-internal (reserved-underscore enum values, no #define, absent in musl / *BSD / macOS), so they can't be feature-detected with #ifdef and are gated on __GLIBC__ — matching the existing glibc-specific code in _localemodule.c.
  • ERA is excluded: it has no bare wide counterpart (_NL_WERA does not exist, only sub-fields like _NL_WERA_D_FMT), so it keeps the narrow path.
  • ALT_DIGITS is a NUL-separated multi-string item and is decoded with a wide analogue of the existing decode_strings() helper.
  • This also unblocks using nl_langinfo() from _strptime for locale-aware parsing without the encoding fragility.

Linked PRs

Activity

  1. added 2 commits that reference this issue on Jul 3, 2026
  2. added 3 commits that reference this issue on Jul 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions