Skip to main content

dtrexp-py

dtrexp-py

Python implementation of DTRExp (read: "DTR Expression") — a compact string expression for date-time ranges and recurrence, evaluated by coverage rather than enumeration.

T0900:1800 E1:5          Mon–Fri, 09:00–18:00
E7#-1 M4                 last Sunday of April, every year
20200106/10D             every 10 days from 2020-01-06 (cron can't say this)
M!7                      every month except July

Scope: parsing, validation and coverage evaluation — the spec's core interface. Rendering, description and RRULE export are out of scope; the reference implementation has them.

Install

pip install dtrexp

Python 3.11+, stdlib only (zoneinfo for IANA zones).

Usage

from datetime import datetime, timezone
import dtrexp

dtr = dtrexp.parse("T0900:1800 E1:5")   # business hours, Mon–Fri

dtr.covers(datetime(2026, 7, 7, 10, 0, tzinfo=timezone.utc))
# —> True (UTC — the default)
dtr.covers(datetime(2026, 7, 7, 7, 30, tzinfo=timezone.utc), tz="Europe/Berlin")
# —> True (09:30 Berlin local time)

Note that you parse once (at write/config time) and evaluate many; Expression objects are immutable, and covers is a single calendar-field extraction followed by integer comparisons (no occurrence iteration). The zone is an evaluation parameter, never part of the expression. covers also accepts an ISO 8601 string for the instant.

Errors and Warnings

Both carry a position; the 0-based character offset into the source:

dtrexp.parse("Y*/3")
# raises DTRExpSyntaxError: "anchorless stride — an explicit start is required (at 1)"
# error.position —> 1

res = dtrexp.validate("D30 M2")   # never raises
res.valid                         # True — it parses
res.warnings                      # (DTRExpWarning(message="unsatisfiable …", position=0),)
  • parse(text) raises DTRExpSyntaxError (a ValueError) on invalid input; position points at the offending character and is appended to the rendered message.
  • validate(text) never raises; typo-shaped input comes back as data. Returns a frozen ValidationResult with valid bool, errors (parsing stops at the first syntax error, so at most one) and warnings.
  • Warnings are the spec's §9.1 unsatisfiability lint: expressions that parse but can never match. They are DTRExpWarning objects (message str, position int | None); str(warning) is the message. Expression.warnings and validate(text).warnings carry the same content.

Conformance & Quality

  • The test suite is driven by the shared vectors.json from the spec repo (draft 2.8): every coverage, rejection, warning and quiet vector, including the calendar traps (Feb 29 across 2000/2024/2100, W53 existence, DST gap/overlap in Europe/Berlin). See VECTORS.md for how the suite works.
  • 100% line + branch coverage, enforced (uv run poe cover); mutation-tested with mutmut (uv run poe mutation).
  • Zero dependencies.

Related Projects

License

© 2026, Onur Yıldırım. MIT License.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dtrexp-1.0.1.tar.gz (71.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dtrexp-1.0.1-py3-none-any.whl (18.4 kB view details)

Uploaded Python 3

File details

Details for the file dtrexp-1.0.1.tar.gz.

File metadata

  • Download URL: dtrexp-1.0.1.tar.gz
  • Upload date:
  • Size: 71.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.27 {"installer":{"name":"uv","version":"0.11.27","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for dtrexp-1.0.1.tar.gz
Algorithm Hash digest
SHA256 9a331e56f7d1eaf0a2a4cd78fd2213ae6a6a0f40f9762c93020093841a0e4fd5
MD5 45d1264eb4ac9550f176e50241785ac2
BLAKE2b-256 741be7d7db79f966b4fb50889605985ad00b02be7c6f54d705dc290a1efe6c19

See more details on using hashes here.

File details

Details for the file dtrexp-1.0.1-py3-none-any.whl.

File metadata

  • Download URL: dtrexp-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 18.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.27 {"installer":{"name":"uv","version":"0.11.27","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for dtrexp-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 9927d335b032515f3ee570b4d44d7cfab9dd87260bf5233eccf2dfec6d232e8b
MD5 41b64fc1c6e793082080c67bb8934665
BLAKE2b-256 6ad5535bdb2af4dbaf42f02436e4fae7e28239e0759ecc3ecdf2ba6229f32bfd

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

1.0.1 This release

2 files

1.0.0

2 files

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