https://github.com/adriamontoto/clock-pattern
The Clock Pattern is a Python ๐ package that turns time into an injectable dependency ๐งฉ. By replacing ad-hoc datetime.now() calls with a swappable Clock interface ๐ฐ๏ธ you unlock deterministic tests ๐งช and decouple business logic from the OS clock.
https://github.com/adriamontoto/clock-pattern
clock dependency-injection development domain-driven-design pattern python python3 python311 python312 python313 utilities
Last synced: 5 months ago
JSON representation
The Clock Pattern is a Python ๐ package that turns time into an injectable dependency ๐งฉ. By replacing ad-hoc datetime.now() calls with a swappable Clock interface ๐ฐ๏ธ you unlock deterministic tests ๐งช and decouple business logic from the OS clock.
- Host: GitHub
- URL: https://github.com/adriamontoto/clock-pattern
- Owner: adriamontoto
- License: mit
- Created: 2025-06-21T09:20:29.000Z (6 months ago)
- Default Branch: master
- Last Pushed: 2025-07-24T03:05:48.000Z (5 months ago)
- Last Synced: 2025-07-25T15:09:03.628Z (5 months ago)
- Topics: clock, dependency-injection, development, domain-driven-design, pattern, python, python3, python311, python312, python313, utilities
- Language: Python
- Homepage: https://pypi.org/project/clock-pattern
- Size: 71.3 KB
- Stars: 2
- Watchers: 0
- Forks: 0
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- Contributing: .github/CONTRIBUTING.md
- Funding: .github/FUNDING.yaml
- License: LICENSE.md
- Code of conduct: .github/CODE_OF_CONDUCT.md
- Citation: CITATION.cff
- Codeowners: .github/CODEOWNERS
- Security: .github/SECURITY.md
Awesome Lists containing this project
README
# ๐ฐ๏ธ Clock Pattern
The **Clock Pattern** is a Python ๐ package that turns time into an injectable dependency ๐งฉ. By replacing ad-hoc datetime.now() calls with a swappable Clock interface ๐ฐ๏ธ you unlock deterministic tests ๐งช, decouple business logic from the OS clock, and gain the freedom to swap in high-precision or logical clocks without touching domain code.
## Table of Contents
- [๐ฅ Installation](#installation)
- [๐ Documentation](#documentation)
- [๐ป Utilization](#utilization)
- [๐ Available Clocks](#available-clocks)
- [๐ Real-Life Case: Christmas Detector Service](#real-life-case-christmas-detector-service)
- [๐ค Contributing](#contributing)
- [๐ License](#license)
## ๐ฅ Installation
You can install **Clock Pattern** using `pip`:
```bash
pip install clock-pattern
```
## ๐ Documentation
This [project's documentation](https://deepwiki.com/adriamontoto/clock-pattern) is powered by DeepWiki, which provides a comprehensive overview of the **Clock Pattern** and its usage.
## ๐ป Utilization
The **Clock Pattern** library is designed to be straightforward. Simply import the desired clock and use its `now()` or `today()` methods to get the current datetime/date. This approach allows for easy dependency injection and testing.
Here is a basic example of how to use the [`SystemClock`](https://github.com/adriamontoto/clock-pattern/blob/master/clock_pattern/clocks/system_clock.py) clock:
```python
from datetime import timezone
from clock_pattern import SystemClock
clock = SystemClock(timezone=timezone.utc)
print(clock.now())
# >>> 2025-06-16 13:57:26.210964+00:00
```
## ๐ Available Clocks
The package offers several clock implementations to suit different needs:
- [`clock_pattern.SystemClock`](https://github.com/adriamontoto/clock-pattern/blob/master/clock_pattern/clocks/system_clock.py): The standard clock implementation that returns the system's current datetime/date with the provided timezone.
- [`clock_pattern.UtcClock`](https://github.com/adriamontoto/clock-pattern/blob/master/clock_pattern/clocks/utc_clock.py): A clock implementation that returns the system's current datetime/date in UTC. Ideal for production environments.
- [`clock_pattern.clocks.testing.FixedClock`](https://github.com/adriamontoto/clock-pattern/blob/master/clock_pattern/clocks/testing/fixed_clock.py): A clock that always returns a fixed, preset datetime/date. It is perfect for basic testing as it allows you to control the datetime/date within your test environment, ensuring deterministic results.
- [`clock_pattern.clocks.testing.MockClock`](https://github.com/adriamontoto/clock-pattern/blob/master/clock_pattern/clocks/testing/mock_clock.py): A clock that allows you to mock the system clock. It is perfect for more complex testing as it allows you to control the datetime/date within your test environment and if or not the methods are called or not.
## ๐ Real-Life Case: Christmas Detector Service
Below is an example of a real-life scenario where Clock Pattern can create clean and testable code. We have a `ChristmasDetectorService` that checks if the curren date falls within a specific Christmas holiday range. Using the Clock Pattern, in this case [`UtcClock`](https://github.com/adriamontoto/clock-pattern/blob/master/clock_pattern/clocks/utc_clock.py) and [`MockClock`](https://github.com/adriamontoto/clock-pattern/blob/master/clock_pattern/clocks/testing/mock_clock.py), we can decouple the service from the python `datetime.now()` and `datetime.today()` functions, making it easy to test for different dates without changing the system's time.
```python
from datetime import date
from clock_pattern import Clock, UtcClock
from clock_pattern.clocks.testing import MockClock
class ChristmasDetectorService:
def __init__(self, clock: Clock) -> None:
self.clock = clock
self.christmas_start = date(year=2024, month=12, day=24)
self.christmas_end = date(year=2025, month=1, day=6)
def is_christmas(self) -> bool:
return self.christmas_start <= self.clock.today() <= self.christmas_end
clock = UtcClock()
christmas_detector_service = ChristmasDetectorService(clock=clock)
print(christmas_detector_service.is_christmas())
# >>> False
def test_christmas_detector_is_christmas() -> None:
clock = MockClock()
christmas_detector_service = ChristmasDetectorService(clock=clock)
today = date(year=2024, month=12, day=25)
clock.prepare_today_method_return_value(today=today)
assert christmas_detector_service.is_christmas() is True
clock.assert_today_method_was_called_once()
def test_christmas_detector_is_not_christmas() -> None:
clock = MockClock()
christmas_detector_service = ChristmasDetectorService(clock=clock)
today = date(year=2025, month=1, day=7)
clock.prepare_today_method_return_value(today=today)
assert christmas_detector_service.is_christmas() is False
clock.assert_today_method_was_called_once()
```
## ๐ค Contributing
We love community help! Before you open an issue or pull request, please read:
- [`๐ค How to Contribute`](https://github.com/adriamontoto/clock-pattern/blob/master/.github/CONTRIBUTING.md)
- [`๐งญ Code of Conduct`](https://github.com/adriamontoto/clock-pattern/blob/master/.github/CODE_OF_CONDUCT.md)
- [`๐ Security Policy`](https://github.com/adriamontoto/clock-pattern/blob/master/.github/SECURITY.md)
_Thank you for helping make **๐ฐ๏ธ Clock Pattern** package awesome! ๐_
## ๐ License
This project is licensed under the terms of the [`MIT license`](https://github.com/adriamontoto/clock-pattern/blob/master/LICENSE.md).