Skip to main content

workclock

Fast, correct business-time arithmetic (working hours, SLAs, shifts) for Python, with a Rust core — a maintained replacement for businesstimedelta, with a compatibility layer for existing code.

Status: pre-1.0; the API may still change in a minor release.

Install

pip install workclock
uv add workclock

Requires CPython 3.9 or later. The wheels use the stable ABI (abi3), one per platform: Linux x86_64 and aarch64 (manylinux and musllinux), macOS x86_64 and arm64, and Windows x64. Free-threaded CPython cannot load abi3 wheels. Other platforms build from the sdist, which needs a Rust toolchain.

The wheels bundle the IANA time zone database. They use the system database when there is one, and the bundled copy otherwise, so they need no tzdata package.

Quickstart

A support desk in London works 09:00–17:00 on weekdays with a lunch hour, and is closed on 25 and 28 December 2026. A ticket opened at 16:30 on Christmas Eve with an 8-hour SLA is due at 09:30 on 30 December.

from datetime import date, datetime, time
from zoneinfo import ZoneInfo

from workclock import Break, Holidays, Schedule, WorkDay

london = ZoneInfo("Europe/London")
support = Schedule(
    [
        WorkDay(time(9), time(17)),  # Monday to Friday by default
        Break(time(12), time(13)),
        Holidays([date(2026, 12, 25), date(2026, 12, 28)]),
    ],
    time_zone=london,
)

opened = datetime(2026, 12, 24, 16, 30, tzinfo=london)
support.add(opened, hours=8)  # 2026-12-30 09:30, London time
support.between(opened, datetime(2026, 12, 29, 11, tzinfo=london))  # 2:30:00
support.next_period(opened)  # (16:30, 17:00) on 24 December

Datetimes must be timezone-aware, and results keep the tzinfo you pass in. Zones can be IANA names, zoneinfo.ZoneInfo, pytz zones or datetime.timezone.utc. Errors subclass workclock.WorkclockError and the matching built-in exception.

Batches and NumPy

between_many, add_many and sub_many take lists of datetimes, or NumPy datetime64 and timedelta64 arrays, and process them in one call:

from datetime import datetime, time, timedelta, timezone

from workclock import Schedule, WorkDay

office = Schedule([WorkDay(time(9), time(17))])
tickets = [datetime(2026, 1, 5, 16, tzinfo=timezone.utc)] * 3
office.add_many(tickets, timedelta(hours=2))  # Tuesday 10:00, three times

Coming from businesstimedelta

Most code written for businesstimedelta runs unchanged on workclock's engine:

import datetime

import workclock.compat as businesstimedelta

rule = businesstimedelta.WorkDayRule(datetime.time(9), datetime.time(17))
friday = datetime.datetime(2026, 1, 9, 16)
friday + businesstimedelta.BusinessTimeDelta(rule, hours=2)  # Monday 10:00 UTC

MIGRATING.md lists where it differs.

Why workclock

Correct

businesstimedelta 1.0.1 has had no release since 2019. workclock fixes:

  • Overnight shifts. A 22:00–06:00 shift counts 0 hours between Monday 22:00 and Tuesday 06:00, and adding 4 hours at Monday 22:00 lands on Wednesday. workclock gives 8 hours and Tuesday 02:00.
  • Crashes past the last holiday (#8, #10): TypeError once a query passes the last date in a holiday list.
  • Infinite loops (#9) when holidays and working hours use different time zones. Every workclock search is bounded.
  • Signed differences (#12): Schedule.between(a, b) is negative when b is before a.
  • DST. Working hours are wall-clock times in each rule's IANA zone, and ambiguous or skipped times resolve the way RFC 5545 and JavaScript Temporal do.

Every rule is specified with examples in DESIGN.md, and the package is checked against a brute-force oracle with property-based tests.

Fast

Medians from a GitHub Actions run on a GitHub-hosted Ubuntu runner (AMD EPYC 7763, 4 cores):

Case businesstimedelta 1.0.1 workclock Speed-up
One call, a 5½-hour span 167 µs 3.89 µs 43×
One call, a year with bank holidays 50.8 ms 85 µs 600×
1,000,000 pairs 9.86 min 2.11 s (between_many on NumPy arrays) 280×

The same single call takes 6.78 µs through workclock.compat. Runner CPUs vary, so the times move from run to run; the speed-ups, measured within one run, carry over better. benchmarks/RESULTS.md has every case with p95s.

Also for Rust and JavaScript

The same engine ships as the workclock crate and the workclock npm package, with the same results in every language.

Prior art & credits

workclock ports the test suite and the API of businesstimedelta by Sebastiaan Boer, released under the MIT license. The ported API is workclock.compat, and the ported tests run against it in CI. The original copyright notice is kept in NOTICE.

License

MIT

Metadata

Release files for workclock 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for workclock 0.1.2
File Size Uploaded Provenance
workclock-0.1.2.tar.gz 47.1 kB With provenance Details

Built distributions (wheels)

Table of built distributions (wheels) for workclock 0.1.2
File
workclock-0.1.2-cp39-abi3-win_amd64.whl CPython 3.9 abi3 Windows x86-64 Details
workclock-0.1.2-cp39-abi3-musllinux_1_2_x86_64.whl CPython 3.9 abi3 Linux musl 1.2+ x86-64 Details
workclock-0.1.2-cp39-abi3-musllinux_1_2_aarch64.whl CPython 3.9 abi3 Linux musl 1.2+ ARM64 Details
workclock-0.1.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.9 abi3 Linux glibc 2.17+ x86-64 Details
workclock-0.1.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl CPython 3.9 abi3 Linux glibc 2.17+ ARM64 Details
workclock-0.1.2-cp39-abi3-macosx_11_0_arm64.whl CPython 3.9 abi3 macOS 11.0+ ARM64 Details
workclock-0.1.2-cp39-abi3-macosx_10_12_x86_64.whl CPython 3.9 abi3 macOS 10.12+ x86-64 Details

Total release size: 4.2 MB

Release files / workclock-0.1.2.tar.gz

Download URL workclock-0.1.2.tar.gz
Size 47.1 kB
Tags Source
SHA-256 checksum
How to use checksums
d09a3941122e8a093f40dd3e5ebf37b39d57eeba61b9b7843b41b93ef143ec0d
BLAKE2b-256 checksum
How to use checksums
5c93ffe65e7bcd4d13ffdd20396ad1bd06e8a858b22432ea5df114708907e963
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 26, 2026.

Transparency log

Release files / workclock-0.1.2-cp39-abi3-win_amd64.whl

Download URL workclock-0.1.2-cp39-abi3-win_amd64.whl
Size 411.5 kB
Tags CPython 3.9 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
2a58728271706d8f51d50aa1856b133aad1148fa0d0b78606a8ac9c63e601c25
BLAKE2b-256 checksum
How to use checksums
3e5cf75f170cdec01fc3133ef3f01c87dfde7f14edc1b8229a32d3b33d30fd6e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 26, 2026.

Transparency log

Release files / workclock-0.1.2-cp39-abi3-musllinux_1_2_x86_64.whl

Download URL workclock-0.1.2-cp39-abi3-musllinux_1_2_x86_64.whl
Size 782.4 kB
Tags CPython 3.9 Linux musl 1.2+ x86-64 abi3
SHA-256 checksum
How to use checksums
d46b4018792c0aaed67243cd072f1082c1abcc67286df8fc97cc1a96f8350310
BLAKE2b-256 checksum
How to use checksums
a4c1102a10b32ab98e11bb6b20fe3e6c6918a1d246933838c7f84341e2645125
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 26, 2026.

Transparency log

Release files / workclock-0.1.2-cp39-abi3-musllinux_1_2_aarch64.whl

Download URL workclock-0.1.2-cp39-abi3-musllinux_1_2_aarch64.whl
Size 758.8 kB
Tags CPython 3.9 Linux musl 1.2+ ARM64 abi3
SHA-256 checksum
How to use checksums
568e11bc8cdf67099d25937621708996b317c838be11c79f1e1659f4ad370419
BLAKE2b-256 checksum
How to use checksums
c061d72a9af574ea7a300482074bc31bccc8b20dd55d5ff0cbcd234856fe31ec
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 26, 2026.

Transparency log

Release files / workclock-0.1.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL workclock-0.1.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 576.7 kB
Tags CPython 3.9 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
b71362f5f3d648c8695e996d47936a807b1218ef7d881b0d2e4b33a16adc64f8
BLAKE2b-256 checksum
How to use checksums
2b615531790fcc2463b5b7f2603bdffef84bad30786233a775783e470f140682
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 26, 2026.

Transparency log

Release files / workclock-0.1.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL workclock-0.1.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 580.1 kB
Tags CPython 3.9 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
454573789a800d6cdb5c2b50ffc7476bf75554da2d1bbc6d2696af7e8ad8a78e
BLAKE2b-256 checksum
How to use checksums
a06ea769337dc13fbfe684b7dfb91e99e709283753a9fa675144fba4f6a367ae
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 26, 2026.

Transparency log

Release files / workclock-0.1.2-cp39-abi3-macosx_11_0_arm64.whl

Download URL workclock-0.1.2-cp39-abi3-macosx_11_0_arm64.whl
Size 528.3 kB
Tags CPython 3.9 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
604bb36e2211e506af8083c059e7d0fd8d2a90afe2e51b2e9ea0131e4892f576
BLAKE2b-256 checksum
How to use checksums
5125e9913fae15edcb2786f784217e58c9c451e8428ea582e9e4e1024aa25a39
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 26, 2026.

Transparency log

Release files / workclock-0.1.2-cp39-abi3-macosx_10_12_x86_64.whl

Download URL workclock-0.1.2-cp39-abi3-macosx_10_12_x86_64.whl
Size 517.9 kB
Tags CPython 3.9 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
3ddccccf16f70ac7d21b1272c655be3e9780fdb5a6c7e6e04e951eae6a14a153
BLAKE2b-256 checksum
How to use checksums
d406d2026d47d3eab6e7743e7f3086ff6fc5700baf04ff1d3c866a04d745dfa1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 26, 2026.

Transparency log

Security for workclock 0.1.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 8 files in this release have been uploaded with provenance metadata.

Select from 8 files

Attestation for workclock-0.1.2.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 26, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page