Skip to content

Add parse_nanoseconds for sub-microsecond duration parsing - #49

Merged
jaraco merged 1 commit into
mainfrom
feature/parse-nanoseconds
Jul 13, 2026
Merged

Add parse_nanoseconds for sub-microsecond duration parsing#49
jaraco merged 1 commit into
mainfrom
feature/parse-nanoseconds

Conversation

@jaraco

@jaraco jaraco commented Jul 13, 2026

Copy link
Copy Markdown
Owner

What

Adds parse_nanoseconds(str) -> Decimal, returning a duration as a Decimal count of nanoseconds so callers can retain sub-microsecond resolution that parse_timedelta necessarily rounds away (a datetime.timedelta only has microsecond resolution).

>>> tempora.parse_nanoseconds('34.2 nsec')
Decimal('34.2')
>>> tempora.parse_nanoseconds('1.6 µs')
Decimal('1600.0')

Bug fix along the way

Reworking the internals surfaced a latent bug: _Saved_NS built a microsecond-resolution timedelta and separately stashed the sub-microsecond remainder, then added both back on resolve() — double-counting the fractional part for microsecond, millisecond, and second values:

>>> tempora.parse_timedelta('1.6 µs')   # before: 3µs
datetime.timedelta(microseconds=2)      # after

_Saved_NS now keeps whole microseconds in td and the exact sub-microsecond remainder in nanoseconds, and resolve() rounds the combined total. Because the full value is retained, total_nanoseconds can reconstruct it at full precision — which is what parse_nanoseconds exposes.

Motivation

Requested by jaraco/pytest-perf#18: pytest-perf compares timeit results, and sub-microsecond timings (e.g. python/importlib_metadata#533) were rounded to timedelta(0), collapsing its variance calculation. pytest-perf will consume parse_nanoseconds.

Coverage is via doctests (coh test, all green).

🤖 Generated with Claude Code

parse_timedelta accumulated sub-microsecond values by building a
microsecond-resolution timedelta and *separately* stashing the
sub-microsecond remainder, then adding both back on resolve(). For
microsecond, millisecond, and second values that double-counted the
fractional part -- e.g. parse_timedelta('1.6 µs') resolved to 3µs
instead of 2µs.

Rework _Saved_NS so td holds only whole microseconds and nanoseconds
holds the exact sub-microsecond remainder, with resolve() rounding the
combined total. This corrects the rounding and, because the full value
is now retained, lets total_nanoseconds reconstruct the parsed value at
sub-microsecond precision.

Expose that via a new parse_nanoseconds() returning a Decimal count of
nanoseconds, for callers -- such as pytest-perf comparing sub-microsecond
timeit results -- that need finer resolution than a timedelta can hold.

Ref jaraco/pytest-perf#18.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@jaraco
jaraco merged commit df32a8f into main Jul 13, 2026
28 checks passed
@jaraco
jaraco deleted the feature/parse-nanoseconds branch July 13, 2026 22:25
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.

1 participant