zeitwide
Is this a business day, and what is the next one? Answers for payment rails (Fedwire, FedACH, FedNow, T2, CHAPS) and public holiday calendars, each with the entry that decided it and the official sources behind it.
pip install zeitwide # needs only httpx
pip install "zeitwide[mcp]" # adds the local MCP server
Offline
ZeitWide() answers from the dataset release bundled with the library. It never touches
the network, and it passes the same conformance suite as the hosted API.
from datetime import date
from zeitwide import ZeitWide
zw = ZeitWide()
zw.is_business_day("US-FEDWIRE", date(2026, 11, 26)).is_business_day # False
answer = zw.next_business_day(["US-FEDWIRE", "EU-T2"], date(2026, 11, 25))
answer.date, [day.date for day in answer.skipped] # 2026-11-27, [2026-11-26]
zw.add_business_days("GB-CHAPS", date(2026, 12, 24), 2).date # 2026-12-30
zw.explain_date("US-FEDWIRE", date(2026, 11, 26)).calendars[0].reason # 'Thanksgiving Day'
zw.list_closures("EU-T2", date(2026, 1, 1), date(2026, 12, 31)).closures
Every answer names its dataset_release, the calendar_revisions it used and the
as_of instant it answers for. Pass as_of= to ask what Zeitwide had recorded at an
earlier moment. A date outside a calendar's published coverage raises OutOfRangeError:
the library never guesses. combine="any_open" asks whether at least one calendar is open
instead of all of them.
Online
With an API key (free from the Zeitwide app), the same calls ask the hosted API. They
return the same types, with the latest data, as_of back to the first recorded version,
and a signed receipt with every answer.
with ZeitWide(key="zw_live_…") as zw:
answer = zw.is_business_day("US-FEDWIRE", date(2026, 11, 26))
answer.receipt.id # 'rcpt_…'
The online types come from api/openapi.yaml through the generated zeitwide.api_types
(make generate-clients; never edit them by hand).
Receipts
Check a receipt offline: its hash, ID, Ed25519 signature, and that its key was valid when
it was issued. The public keys are a bundled copy of /.well-known/zeitwide-keys.json
(--keys or KeyRing.parse(...) to use a newer ring).
zeitwide verify answer.json # a receipt, or an answer that carries one; '-' for stdin
from zeitwide import verify_receipt
verify_receipt(answer.receipt) # Verification(valid=True, …), falsy when invalid
Webhooks
from zeitwide import webhooks
event = webhooks.verify(request.body, request.headers["Zeitwide-Signature"], secret)
It checks the HMAC-SHA256 signature over the raw body and refuses deliveries signed more
than five minutes from now. It returns the event only once verified, and raises
WebhookVerificationError otherwise.
Local MCP server
uvx zeitwide-mcp --offline
--offline answers from the bundled release. Without it, the server asks the hosted API
with the key in ZEITWIDE_API_KEY. With the library installed, zeitwide mcp --offline
runs the same server. In an MCP client:
{ "mcpServers": { "zeitwide": { "command": "uvx", "args": ["zeitwide-mcp", "--offline"] } } }
Tools: is_business_day, next_business_day, add_business_days, explain_date and
list_closures, with the same names, arguments and answers as the hosted server at
/mcp (offline answers have no receipt), plus verify_webhook.
Licenses
The code is MIT (LICENSE). The bundled dataset is under CC BY-NC 4.0 (LICENSE-DATA); commercial use of the data needs the hosted API or a separate agreement.
Development
uv sync --all-packages
uv run python -m ruff format . && uv run python -m ruff check .
uv run python -m mypy
uv run python -m pytest --cov
The bundled release in src/zeitwide/data/releases/ must be the newest file in
dataset/releases/ (a test checks); copy a new release there when one is cut. The
zeitwide-mcp/ folder is a launcher package so uvx zeitwide-mcp works; keep its version
in step. Tag lib-python-v<version> to publish both to PyPI
(.github/workflows/publish-lib-python.yml). The library supports Python 3.12 and later,
and CI tests 3.12, 3.13 and 3.14.
Metadata
Release files for zeitwide 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| zeitwide-0.1.0.tar.gz | 36.0 kB | Without provenance | Details for zeitwide-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| zeitwide-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for zeitwide-0.1.0-py3-none-any.whl |
Total release size: 77.7 kB
Release files / zeitwide-0.1.0.tar.gz
| Download URL | zeitwide-0.1.0.tar.gz |
|---|---|
| Size | 36.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
bbfda83b1eb7eb1075e2b147b193c2a5a7b6f2136784d028ccfc12d50d44ecff
|
|
BLAKE2b-256 checksum How to use checksums |
1817bcb49d57b78b1e1168cadc0c42e6b238ca3d77797254e88896fd008d3f7b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.6 {"installer":{"name":"uv","version":"0.13.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / zeitwide-0.1.0-py3-none-any.whl
| Download URL | zeitwide-0.1.0-py3-none-any.whl |
|---|---|
| Size | 41.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e6513bc8afc67c88f2a417711762c8be3bbc285f93a1eaca67fc8293148048f9
|
|
BLAKE2b-256 checksum How to use checksums |
c278b95523cc87478209a48a647ec9be08a4cc68b886badda8ad911c650e5cbb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.6 {"installer":{"name":"uv","version":"0.13.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for zeitwide 0.1.0
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
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.