Strict datetime safety layer and CI linter for Python backend reliability
Project description
time_unifier
time_unifier is not a datetime library.
It is a strict datetime safety layer + CI guardrail for backend systems.
Positioning: time_unifier prevents production incidents caused by datetime misuse.
30-Second Quickstart
pip install time_unifier
pip install -e . # for local development
time-unifier check .
Minimal Real Example (Bug Caught + Fixed)
# bad
from datetime import datetime
created = datetime.utcnow()
# linter catch
# TU002 datetime.utcnow() usage detected
# fixed
from datetime import datetime, timezone
created = datetime.now(timezone.utc)
Core Philosophy
- UTC internally
- Zoned time at boundaries only
- No naive datetime
- No implicit conversions
- Explicit conversion everywhere
Real Bugs This Prevents
JWT expiry drift
- Bad code:
datetime.utcnow() + timedelta(...) - Why tests pass: single timezone CI environment
- Why production fails: services interpret naive timestamps differently
- How caught:
TU002+ strict runtime parsing
Scheduling errors
- Bad code:
datetime.fromtimestamp(ts) - Why tests pass: developer/CI host timezone matches assumption
- Why production fails: workers in different regions schedule at different wall times
- How caught:
TU004+ autofix totz=timezone.utc
Timezone ordering bugs
- Bad code: comparing datetime objects with string timestamps or mixed awareness
- Why tests pass: happy-path lexical ordering
- Why production fails: DST and offset shifts reorder events
- How caught:
TU012+TU013
Why not Pendulum/Arrow?
Pendulum and Arrow improve datetime ergonomics. They do not provide guardrails as workflow enforcement:
- no CI policy enforcement over your codebase
- no strict UTC-only backend boundary contract
- no static type guard against UTC/Zoned misuse
Comparison
| Capability | time_unifier | Pendulum | Arrow | Ruff datetime rules |
|---|---|---|---|---|
| Strict UTC runtime contract | Yes | No | No | No |
| Zoned boundary separation | Yes | Partial | Partial | No |
| CI-enforced datetime linting | Yes | No | No | Partial |
| Autofix for backend datetime hazards | Yes | No | No | Partial |
| mypy static UTC/Zoned safety | Yes | No | No | No |
How time_unifier Prevents Bugs Before Deployment
- Runtime safety types reject ambiguous datetimes (
UTCTime,ZonedTime). - Linter blocks unsafe patterns in PRs (
TU001-TU015). - Autofix rewrites common high-risk patterns safely.
- mypy plugin catches mixed UTC/Zoned misuse at type-check time.
- CI integration fails builds before risky code merges.
CLI UX
time-unifier check . --fail-on error
time-unifier check . --fix
Output format:
path:line:column: RULE message
consequence: real backend impact
suggestion: exact fix
Exit behavior:
--fail-on error: exit non-zero only if anyerrorfindings exist.--fail-on warning: exit non-zero for any finding.
Integration in Developer Workflow
GitHub Action
Use .github/workflows/time-unifier.yml to run:
time-unifier check .
pre-commit
repos:
- repo: local
hooks:
- id: time-unifier
name: time-unifier
entry: time-unifier check .
language: system
Ruff compatibility (no conflict)
- Run Ruff and
time-unifierside by side in CI. - Keep Ruff for style/quality; keep
time_unifierfor strict datetime safety policy. - Do not replace one with the other; they are complementary.
Integrations
- Pydantic: strict typed field validation
- FastAPI: explicit UTC/zoned boundary parsing
- SQLAlchemy: UTC-only DB boundary type
Examples and Migration
- Examples:
examples/auth_jwt_expiry.py,examples/scheduler_bug.py,examples/event_ordering_bug.py - Migration guide:
docs/MIGRATION.md
What This Is Not
- Not a replacement for
datetime - Not a convenience datetime toolkit
- Not a scheduling framework
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file time_unifier-0.1.2.tar.gz.
File metadata
- Download URL: time_unifier-0.1.2.tar.gz
- Upload date:
- Size: 25.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
591dc00b28ae0882652bbd33525fc44e3b7dd874c6a54eeade9eb019fbfbd633
|
|
| MD5 |
2e439f6d0dfbcb350e08a97963179c79
|
|
| BLAKE2b-256 |
38220c546793038928835ec3c5671200f9ece01c3b6d8b595107e498faeae2a7
|
File details
Details for the file time_unifier-0.1.2-py3-none-any.whl.
File metadata
- Download URL: time_unifier-0.1.2-py3-none-any.whl
- Upload date:
- Size: 25.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d9c478cd43f3721f09ee2522328aa95ce60a22814eb1495b7c4d601b9e415ab8
|
|
| MD5 |
700e8cba35eb1183c131a159a490a9eb
|
|
| BLAKE2b-256 |
a7c56857f2332aa5b6ca3a4adb49005f626b4275ac2a7697f55fcb6f311dd2b6
|