{"id":28939300,"url":"https://github.com/adriamontoto/clock-pattern","last_synced_at":"2025-07-28T14:08:08.670Z","repository":{"id":300375540,"uuid":"1006004952","full_name":"adriamontoto/clock-pattern","owner":"adriamontoto","description":"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.","archived":false,"fork":false,"pushed_at":"2025-07-24T03:05:48.000Z","size":73,"stargazers_count":2,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-07-25T15:09:03.628Z","etag":null,"topics":["clock","dependency-injection","development","domain-driven-design","pattern","python","python3","python311","python312","python313","utilities"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/clock-pattern","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/adriamontoto.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":".github/CONTRIBUTING.md","funding":".github/FUNDING.yaml","license":"LICENSE.md","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":"CITATION.cff","codeowners":".github/CODEOWNERS","security":".github/SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":["adriamontoto"]}},"created_at":"2025-06-21T09:20:29.000Z","updated_at":"2025-07-23T18:30:24.000Z","dependencies_parsed_at":"2025-06-21T10:52:01.201Z","dependency_job_id":null,"html_url":"https://github.com/adriamontoto/clock-pattern","commit_stats":null,"previous_names":["adriamontoto/clock-pattern"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/adriamontoto/clock-pattern","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adriamontoto%2Fclock-pattern","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adriamontoto%2Fclock-pattern/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adriamontoto%2Fclock-pattern/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adriamontoto%2Fclock-pattern/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/adriamontoto","download_url":"https://codeload.github.com/adriamontoto/clock-pattern/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adriamontoto%2Fclock-pattern/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267527835,"owners_count":24102019,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-28T02:00:09.689Z","response_time":68,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["clock","dependency-injection","development","domain-driven-design","pattern","python","python3","python311","python312","python313","utilities"],"created_at":"2025-06-23T00:08:13.953Z","updated_at":"2025-07-28T14:08:08.660Z","avatar_url":"https://github.com/adriamontoto.png","language":"Python","funding_links":["https://github.com/sponsors/adriamontoto"],"categories":[],"sub_categories":[],"readme":"\u003ca name=\"readme-top\"\u003e\u003c/a\u003e\n\n# 🕰️ Clock Pattern\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://github.com/adriamontoto/clock-pattern/actions/workflows/ci.yaml?event=push\u0026branch=master\" target=\"_blank\"\u003e\n        \u003cimg src=\"https://github.com/adriamontoto/clock-pattern/actions/workflows/ci.yaml/badge.svg?event=push\u0026branch=master\" alt=\"CI Pipeline\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://coverage-badge.samuelcolvin.workers.dev/redirect/adriamontoto/clock-pattern\" target=\"_blank\"\u003e\n        \u003cimg src=\"https://coverage-badge.samuelcolvin.workers.dev/adriamontoto/clock-pattern.svg\" alt=\"Coverage Pipeline\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://pypi.org/project/clock-pattern\" target=\"_blank\"\u003e\n        \u003cimg src=\"https://img.shields.io/pypi/v/clock-pattern?color=%2334D058\u0026label=pypi%20package\" alt=\"Package Version\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://pypi.org/project/clock-pattern/\" target=\"_blank\"\u003e\n        \u003cimg src=\"https://img.shields.io/pypi/pyversions/clock-pattern.svg?color=%2334D058\" alt=\"Supported Python Versions\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://pepy.tech/projects/clock-pattern\" target=\"_blank\"\u003e\n        \u003cimg src=\"https://static.pepy.tech/badge/clock-pattern/month\" alt=\"Package Downloads\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://deepwiki.com/adriamontoto/clock-pattern\" target=\"_blank\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/DeepWiki-adriamontoto%2Fclock--pattern-blue.svg?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAyCAYAAAAnWDnqAAAAAXNSR0IArs4c6QAAA05JREFUaEPtmUtyEzEQhtWTQyQLHNak2AB7ZnyXZMEjXMGeK/AIi+QuHrMnbChYY7MIh8g01fJoopFb0uhhEqqcbWTp06/uv1saEDv4O3n3dV60RfP947Mm9/SQc0ICFQgzfc4CYZoTPAswgSJCCUJUnAAoRHOAUOcATwbmVLWdGoH//PB8mnKqScAhsD0kYP3j/Yt5LPQe2KvcXmGvRHcDnpxfL2zOYJ1mFwrryWTz0advv1Ut4CJgf5uhDuDj5eUcAUoahrdY/56ebRWeraTjMt/00Sh3UDtjgHtQNHwcRGOC98BJEAEymycmYcWwOprTgcB6VZ5JK5TAJ+fXGLBm3FDAmn6oPPjR4rKCAoJCal2eAiQp2x0vxTPB3ALO2CRkwmDy5WohzBDwSEFKRwPbknEggCPB/imwrycgxX2NzoMCHhPkDwqYMr9tRcP5qNrMZHkVnOjRMWwLCcr8ohBVb1OMjxLwGCvjTikrsBOiA6fNyCrm8V1rP93iVPpwaE+gO0SsWmPiXB+jikdf6SizrT5qKasx5j8ABbHpFTx+vFXp9EnYQmLx02h1QTTrl6eDqxLnGjporxl3NL3agEvXdT0WmEost648sQOYAeJS9Q7bfUVoMGnjo4AZdUMQku50McDcMWcBPvr0SzbTAFDfvJqwLzgxwATnCgnp4wDl6Aa+Ax283gghmj+vj7feE2KBBRMW3FzOpLOADl0Isb5587h/U4gGvkt5v60Z1VLG8BhYjbzRwyQZemwAd6cCR5/XFWLYZRIMpX39AR0tjaGGiGzLVyhse5C9RKC6ai42ppWPKiBagOvaYk8lO7DajerabOZP46Lby5wKjw1HCRx7p9sVMOWGzb/vA1hwiWc6jm3MvQDTogQkiqIhJV0nBQBTU+3okKCFDy9WwferkHjtxib7t3xIUQtHxnIwtx4mpg26/HfwVNVDb4oI9RHmx5WGelRVlrtiw43zboCLaxv46AZeB3IlTkwouebTr1y2NjSpHz68WNFjHvupy3q8TFn3Hos2IAk4Ju5dCo8B3wP7VPr/FGaKiG+T+v+TQqIrOqMTL1VdWV1DdmcbO8KXBz6esmYWYKPwDL5b5FA1a0hwapHiom0r/cKaoqr+27/XcrS5UwSMbQAAAABJRU5ErkJggg==\" alt=\"Project Documentation\"\u003e\n    \u003c/a\u003e\n\u003c/p\u003e\n\nThe **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.\n\u003cbr\u003e\u003cbr\u003e\n\n## Table of Contents\n\n- [📥 Installation](#installation)\n- [📚 Documentation](#documentation)\n- [💻 Utilization](#utilization)\n  - [📚 Available Clocks](#available-clocks)\n  - [🎄 Real-Life Case: Christmas Detector Service](#real-life-case-christmas-detector-service)\n- [🤝 Contributing](#contributing)\n- [🔑 License](#license)\n\n\u003cp align=\"right\"\u003e\n    \u003ca href=\"#readme-top\"\u003e🔼 Back to top\u003c/a\u003e\n\u003c/p\u003e\u003cbr\u003e\u003cbr\u003e\n\n\u003ca name=\"installation\"\u003e\u003c/a\u003e\n\n## 📥 Installation\n\nYou can install **Clock Pattern** using `pip`:\n\n```bash\npip install clock-pattern\n```\n\n\u003cp align=\"right\"\u003e\n    \u003ca href=\"#readme-top\"\u003e🔼 Back to top\u003c/a\u003e\n\u003c/p\u003e\u003cbr\u003e\u003cbr\u003e\n\n\u003ca name=\"documentation\"\u003e\u003c/a\u003e\n\n## 📚 Documentation\n\nThis [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.\n\n\u003cp align=\"right\"\u003e\n    \u003ca href=\"#readme-top\"\u003e🔼 Back to top\u003c/a\u003e\n\u003c/p\u003e\u003cbr\u003e\u003cbr\u003e\n\n\u003ca name=\"utilization\"\u003e\u003c/a\u003e\n\n## 💻 Utilization\n\nThe **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.\n\nHere 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:\n\n```python\nfrom datetime import timezone\n\nfrom clock_pattern import SystemClock\n\nclock = SystemClock(timezone=timezone.utc)\nprint(clock.now())\n# \u003e\u003e\u003e 2025-06-16 13:57:26.210964+00:00\n```\n\n\u003cp align=\"right\"\u003e\n    \u003ca href=\"#readme-top\"\u003e🔼 Back to top\u003c/a\u003e\n\u003c/p\u003e\u003cbr\u003e\u003cbr\u003e\n\n\u003ca name=\"available-clocks\"\u003e\u003c/a\u003e\n\n## 📚 Available Clocks\n\nThe package offers several clock implementations to suit different needs:\n\n- [`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.\n- [`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.\n- [`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.\n- [`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.\n\u003cp align=\"right\"\u003e\n    \u003ca href=\"#readme-top\"\u003e🔼 Back to top\u003c/a\u003e\n\u003c/p\u003e\u003cbr\u003e\u003cbr\u003e\n\n\u003ca name=\"real-life-case-christmas-detector-service\"\u003e\u003c/a\u003e\n\n## 🎄 Real-Life Case: Christmas Detector Service\n\nBelow 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.\n\n```python\nfrom datetime import date\n\nfrom clock_pattern import Clock, UtcClock\nfrom clock_pattern.clocks.testing import MockClock\n\n\nclass ChristmasDetectorService:\n    def __init__(self, clock: Clock) -\u003e None:\n        self.clock = clock\n        self.christmas_start = date(year=2024, month=12, day=24)\n        self.christmas_end = date(year=2025, month=1, day=6)\n\n    def is_christmas(self) -\u003e bool:\n        return self.christmas_start \u003c= self.clock.today() \u003c= self.christmas_end\n\n\nclock = UtcClock()\nchristmas_detector_service = ChristmasDetectorService(clock=clock)\n\nprint(christmas_detector_service.is_christmas())\n# \u003e\u003e\u003e False\n\n\ndef test_christmas_detector_is_christmas() -\u003e None:\n    clock = MockClock()\n    christmas_detector_service = ChristmasDetectorService(clock=clock)\n\n    today = date(year=2024, month=12, day=25)\n    clock.prepare_today_method_return_value(today=today)\n\n    assert christmas_detector_service.is_christmas() is True\n    clock.assert_today_method_was_called_once()\n\n\ndef test_christmas_detector_is_not_christmas() -\u003e None:\n    clock = MockClock()\n    christmas_detector_service = ChristmasDetectorService(clock=clock)\n\n    today = date(year=2025, month=1, day=7)\n    clock.prepare_today_method_return_value(today=today)\n\n    assert christmas_detector_service.is_christmas() is False\n    clock.assert_today_method_was_called_once()\n```\n\n\u003cp align=\"right\"\u003e\n    \u003ca href=\"#readme-top\"\u003e🔼 Back to top\u003c/a\u003e\n\u003c/p\u003e\u003cbr\u003e\u003cbr\u003e\n\n\u003ca name=\"contributing\"\u003e\u003c/a\u003e\n\n## 🤝 Contributing\n\nWe love community help! Before you open an issue or pull request, please read:\n\n- [`🤝 How to Contribute`](https://github.com/adriamontoto/clock-pattern/blob/master/.github/CONTRIBUTING.md)\n- [`🧭 Code of Conduct`](https://github.com/adriamontoto/clock-pattern/blob/master/.github/CODE_OF_CONDUCT.md)\n- [`🔐 Security Policy`](https://github.com/adriamontoto/clock-pattern/blob/master/.github/SECURITY.md)\n\n_Thank you for helping make **🕰️ Clock Pattern** package awesome! 🌟_\n\n\u003cp align=\"right\"\u003e\n    \u003ca href=\"#readme-top\"\u003e🔼 Back to top\u003c/a\u003e\n\u003c/p\u003e\u003cbr\u003e\u003cbr\u003e\n\n\u003ca name=\"license\"\u003e\u003c/a\u003e\n\n## 🔑 License\n\nThis project is licensed under the terms of the [`MIT license`](https://github.com/adriamontoto/clock-pattern/blob/master/LICENSE.md).\n\n\u003cp align=\"right\"\u003e\n    \u003ca href=\"#readme-top\"\u003e🔼 Back to top\u003c/a\u003e\n\u003c/p\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadriamontoto%2Fclock-pattern","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fadriamontoto%2Fclock-pattern","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadriamontoto%2Fclock-pattern/lists"}