Repository navigation
Conversation
Documentation build overview
18 files changed ·
|
Read ASCII names from the current locale without caching them across setlocale calls. Preserve explicitly supplied weekdays in time.strptime, including numeric weekdays and weekdays that disagree with the date. Non-ASCII names and mixed spellings of a field retain the Python parser.
Use the current locale for AM/PM indicators and preserve the default without an indicator. Include the equivalent %k, %l and %P directives. Locales with empty or non-ASCII indicators retain the Python parser.
Allow nonterminal offsets, offset seconds and fractions, and %:z. Preserve fractional offsets for datetime and time objects, and preserve terminal UTC/GMT names and DST metadata for time.strptime. Local timezone names and nonterminal %Z still use the Python parser.
Expand %F, %D, %T and %R through the same field parser without allocating a temporary format string. Include %e and the optional whitespace directives %n and %t.
Calculate dates for %j, %U/%W and %G/%V using the shared Gregorian calendar helpers. Preserve explicit weekdays and time.strptime yday values when a week or ordinal date crosses a year boundary.
Use the same whitespace predicate as Python for %n, %t, and trimming AM/PM indicators. Cover ASCII separators before adjacent numeric fields in the alias formats.
pganssle
force-pushed
the
c-strptime-more-formats
branch
from
October 23, 2026 17:11
da4922b to
5cc3575
Compare
Common numeric directives were passing through alias and locale-name checks before parsing their digits. Look up equivalent fields directly in the directive table and dispatch once to select the parsing rules. Compute missing weekdays in time.strptime, so the datetime methods avoid work they don't use. Keep weekdays supplied by the input or calculated from ordinal dates intact. Add coverage for mixed directive spellings and inferred weekdays.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follows #158253, now merged.
This extends the shared C parser used by
datetime.datetime.strptime,datetime.date.strptime,datetime.time.strptime, andtime.strptime.The format groups are separate commits, ordered by the usage survey:
%b,%B,%a,%A, plus numeric weekdays%wand%u.%Iand%p, plus%k,%l, and%P.%z, offset seconds and fractions,%:z, and terminalUTC/GMTnames with%Z.%F,%D,%T,%R,%e,%n, and%t.%j,%U,%W,%G, and%V.Locale names are read on each call, so there is no cache to invalidate after
setlocale(). Explicit weekdays and timezone names are preserved intime.strptimeresults.Non-ASCII input and name sets, empty AM/PM indicators, locale composites such as
%c, local timezone names, and nonterminal%Zretain the Python parser. Parser mismatches, mixed spellings of a field, and matches requiring backtracking also fall back. The one-argument form oftime.strptimeis unchanged.After rebasing onto upstream main,
test_strptime,test_time, andtest_datetimepass, along with 3,840 benchmark correctness checks. Before this rebase, 96,000 comparisons against the Python parser across C, French, German, and Japanese locales passed, as did the documentation build. Free-threaded debug tests and repeated leak checks passed before the earlier rebase.The benchmarks below were collected before the rebase, comparing
510c6226ec6with071bc0bd031. They have not been rerun against the current base and head. Both builds used GCC 16.2.1 andCFLAGS="-O3 -g -fno-omit-frame-pointer", without PGO or LTO. Each case uses the same 32 inputs for all four APIs. Two runs per revision alternate before/after/after/before, with three worker processes and three measured values per run. The numeric-date and Unicode-fallback rows use longer repeats with six workers, five values, and a 50 ms minimum sample time, after the initial measurements showed substantial variation. Most rows are still short runs; small differences need more measurement.These earlier measurements show speedups for the added formats and overhead for some existing numeric formats. The table includes two of those slower cases; the complete results are below.
—means the difference was not statistically significant, and‡marks cases that still use the Python parser.Selected
datetime.datetime.strptimeresults:%Y-%m-%d%Y-%m-%d %H:%M:%S%b %d, %Y%d %B %Y %H:%M:%S%a, %d %b %Y %H:%M:%S GMT%Y-%m-%d %I:%M:%S %p%Y-%m-%d %H:%M:%S %Z(UTC)%Y-%m-%dT%H:%M:%S%z(+053012.345678)%Y-%m-%d %z %H:%M:%S(+0530)%F%F %T%Y-%j%G-W%V-%u%Y-%W-%wComplete benchmarks for all four entry points
datetime.datetime.strptime%Y-%m-%d%Y%m%d%Y/%m/%d%m/%d/%Y%d/%m/%Y%Y-%m-%d %H:%M:%S%Y-%m-%d %H:%M:%S.%f%Y%m%d%H%M%S%Y-%m-%dT%H:%M:%S%z(UTC)%Y-%m-%dT%H:%M:%SZ%Y-%m-%dT%H:%M:%S.%fZ%Y-%m-%dT%H:%M:%S.%f%z(+0530)%H:%M:%S%H:%M:%S.%f%z(+0530)%d %B %Y %H:%M:%S%b %d, %Y%a, %d %b %Y %H:%M:%S GMT%Y-%m-%d %I:%M:%S %p%Y-%m-%dT%H:%M:%S%z(+053012.345678)%Y-%m-%d %z %H:%M:%S(+0530)%Y-%m-%d %H:%M:%S %Z(UTC)%F%F %T%Y-%j%G-W%V-%u%Y-%W-%w%Y-%m-%d %H:%M:%S+ rotating suffix%d %B %Y %H:%M:%S+ rotating suffix%c‡%Y年%m月%d日‡datetime.date.strptime%Y-%m-%d%Y%m%d%Y/%m/%d%m/%d/%Y%d/%m/%Y%Y-%m-%d %H:%M:%S%Y-%m-%d %H:%M:%S.%f%Y%m%d%H%M%S%Y-%m-%dT%H:%M:%S%z(UTC)%Y-%m-%dT%H:%M:%SZ%Y-%m-%dT%H:%M:%S.%fZ%Y-%m-%dT%H:%M:%S.%f%z(+0530)%H:%M:%S%H:%M:%S.%f%z(+0530)%d %B %Y %H:%M:%S%b %d, %Y%a, %d %b %Y %H:%M:%S GMT%Y-%m-%d %I:%M:%S %p%Y-%m-%dT%H:%M:%S%z(+053012.345678)%Y-%m-%d %z %H:%M:%S(+0530)%Y-%m-%d %H:%M:%S %Z(UTC)%F%F %T%Y-%j%G-W%V-%u%Y-%W-%w%Y-%m-%d %H:%M:%S+ rotating suffix%d %B %Y %H:%M:%S+ rotating suffix%c‡%Y年%m月%d日‡datetime.time.strptime%Y-%m-%d%Y%m%d%Y/%m/%d%m/%d/%Y%d/%m/%Y%Y-%m-%d %H:%M:%S%Y-%m-%d %H:%M:%S.%f%Y%m%d%H%M%S%Y-%m-%dT%H:%M:%S%z(UTC)%Y-%m-%dT%H:%M:%SZ%Y-%m-%dT%H:%M:%S.%fZ%Y-%m-%dT%H:%M:%S.%f%z(+0530)%H:%M:%S%H:%M:%S.%f%z(+0530)%d %B %Y %H:%M:%S%b %d, %Y%a, %d %b %Y %H:%M:%S GMT%Y-%m-%d %I:%M:%S %p%Y-%m-%dT%H:%M:%S%z(+053012.345678)%Y-%m-%d %z %H:%M:%S(+0530)%Y-%m-%d %H:%M:%S %Z(UTC)%F%F %T%Y-%j%G-W%V-%u%Y-%W-%w%Y-%m-%d %H:%M:%S+ rotating suffix%d %B %Y %H:%M:%S+ rotating suffix%c‡%Y年%m月%d日‡time.strptime%Y-%m-%d%Y%m%d%Y/%m/%d%m/%d/%Y%d/%m/%Y%Y-%m-%d %H:%M:%S%Y-%m-%d %H:%M:%S.%f%Y%m%d%H%M%S%Y-%m-%dT%H:%M:%S%z(UTC)%Y-%m-%dT%H:%M:%SZ%Y-%m-%dT%H:%M:%S.%fZ%Y-%m-%dT%H:%M:%S.%f%z(+0530)%H:%M:%S%H:%M:%S.%f%z(+0530)%d %B %Y %H:%M:%S%b %d, %Y%a, %d %b %Y %H:%M:%S GMT%Y-%m-%d %I:%M:%S %p%Y-%m-%dT%H:%M:%S%z(+053012.345678)%Y-%m-%d %z %H:%M:%S(+0530)%Y-%m-%d %H:%M:%S %Z(UTC)%F%F %T%Y-%j%G-W%V-%u%Y-%W-%w%Y-%m-%d %H:%M:%S+ rotating suffix%d %B %Y %H:%M:%S+ rotating suffix%c‡%Y年%m月%d日‡Benchmark reproducer
Build both revisions with the configure options above and
--without-ensurepip, installpyperf==2.9.0into a shared dependency directory, and save the script below asbenchmark.py. For each interpreter:PYTHONPATH=/path/to/deps /path/to/python benchmark.py --smoke PYTHONPATH=/path/to/deps /path/to/python benchmark.py \ --inherit-environ=PYTHONPATH --affinity=2 \ -p 3 -n 3 -w 1 --min-time=0.01 -o run.jsonChoose an available CPU for
--affinity, and use a different output file for each run. The comparison uses two runs per revision in before/after/after/before order.For the longer repeats, add
--case numeric_dateor--case unicode_dateand--method datetime,date,datetime_time, ortime, and replace the timing options with-p 6 -n 5 -w 2 --min-time=0.05.