Skip to content

Benchmarks

How fast each binding is, measured against businesstimedelta 1.0.1 and a hand-written standard-library loop.

The Rust, Python and JavaScript bindings are timed on the same three cases, against businesstimedelta 1.0.1 and against the loop you would write with each language's standard library. The Python suite also times workclock.compat. The cases and the commands come from benchmarks/README.md. The numbers in benchmarks/RESULTS.md come from the Benchmarks workflow on a GitHub-hosted Ubuntu runner, and RESULTS.md links the run, so anyone can open it.

Runner CPUs vary from run to run. On 2026-10-26, three runs on AMD EPYC 7763 and Intel Xeon 8573C runners moved the times by up to about 20%, while the speed-ups over businesstimedelta, measured in the same run, stayed within about 6%. Compare the "vs businesstimedelta" and "vs stdlib" columns rather than raw times.

CI also counts instructions under Valgrind for Rust and Python, and fails a pull request whose single or year case executes more than 3% more instructions. Instruction counts has the details.

Cases

The Rust, Python and JavaScript suites measure the same three cases, all with one schedule: Europe/London, Monday to Friday 09:00–17:00, a 12:00–13:00 break, and the bank holidays of England in 2026 and 2027. The 2027 ones are there because businesstimedelta 1.0.1 raises TypeError for instants after its last holiday (upstream issue 8).

CaseCall
singlebetween Tuesday 2026-03-10 10:15 and 15:45 UTC
yearbetween 2026-01-01 and 2027-01-01 UTC
batchbetween for 1,000,000 pairs: pair i starts i * 7919 mod 525600 minutes into 2026 and lasts i * 104729 mod 10080 minutes

Building the schedule and the pairs is not timed.

Standard-library baselines

Neither Python nor JavaScript can compute working time out of the box, so each suite also times stdlib: the loop a developer would write for this one schedule with the standard library alone. It walks the local dates from the first instant to the second, skips weekends and holidays, and adds the overlap with 09:00–12:00 and 13:00–17:00 London time.

LanguageBaselineBuilt on
Pythonbenchmarks/python/stdlib.pydatetime and zoneinfo
JavaScriptjs/bench/stdlib.tsTemporal, on by default from Node.js 26

Tests check both against workclock on the single and year cases, both daylight saving changes, Easter, a reversed pair and 10,000 batch pairs, so every speed-up compares code that gives the same answers. RESULTS.md divides each language's stdlib median by every row's median in its "vs stdlib" column. Rust's standard library has no time zones, so Rust has no baseline.

Running

cargo bench -p workclock --bench workclock
uv run pytest benchmarks/python
cd js && npm run build:node && npm run bench

The JavaScript suite needs Node.js 26, for Temporal.

The Python suite also measures workclock's compat API, between_many on lists and on NumPy arrays, and businesstimedelta 1.0.1. It runs the single case on compat and businesstimedelta a second time with a python-holidays object for England in place of the list; compat fills it in for 1970 to 2100. One round of the batch case takes businesstimedelta about half an hour; add -k "not (test_batch and businesstimedelta)" to skip it.

The JavaScript suite runs the batch case three ways: between in a loop, and betweenMany on arrays of Dates and on Float64Arrays.

Results

Cases and commands are in README.md.

Machine
Date2026-10-26
Run40285792116
RunnerGitHub-hosted ubuntu24, image 20261023.334.3
CPUAMD EPYC 7763 64-Core Processor, 4 logical cores
Memory16 GiB
OSLinux-6.17.0-1022-azure-x86_64-with-glibc2.39
Rustrustc 1.99.1 (58cf8f9c3 2026-10-13)
Python3.15.1
Node.jsv26.12.1

single

ImplementationMedianp95Samplesvs businesstimedeltavs stdlib
Rust1.19 µs1.2 µs100140×
JavaScript1.77 µs1.81 µs110959895×5.1×
Python, workclock3.96 µs4.08 µs5056443×1×
Python, stdlib4.01 µs4.12 µs4190342×1×
Python, workclock.compat, python-holidays6.93 µs7.33 µs182924×0.58×
Python, workclock.compat7.24 µs14 µs942723×0.55×
JavaScript, stdlib9.06 µs9.6 µs17316619×1×
Python, businesstimedelta169 µs182 µs38791×0.024×
Python, businesstimedelta, python-holidays196 µs210 µs27900.86×0.02×

year

ImplementationMedianp95Samplesvs businesstimedeltavs stdlib
Rust84.5 µs86.9 µs100630×
Python, workclock85.4 µs96.1 µs8093620×8.4×
Python, workclock.compat88.7 µs100 µs5481600×8.1×
JavaScript106 µs114 µs18747500×16×
Python, stdlib719 µs747 µs125674×1×
JavaScript, stdlib1.71 ms1.74 ms89131×1×
Python, businesstimedelta53 ms54.7 ms191×0.014×

batch

ImplementationMedianp95Samplesvs businesstimedeltavs stdlib
Rust1.96 s1.97 s10300×
Python, workclock between_many, NumPy2.13 s2.15 s5280×4.7×
JavaScript, betweenMany, Float64Array2.54 s2.55 s5230×15×
JavaScript, between in a loop2.68 s2.68 s5220×14×
JavaScript, betweenMany, Dates2.68 s2.71 s5220×14×
Python, workclock between_many3.42 s3.45 s5170×2.9×
Python, workclock4.6 s4.62 s3130×2.2×
Python, workclock.compat7.99 s8.01 s374×1.2×
Python, stdlib9.95 s9.95 s360×1×
JavaScript, stdlib38.3 s39 s516×1×
Python, businesstimedelta9.9 min9.9 min11×0.017×

Report a problem with this pageAsk a question in Discussions

On this page