{"id":51514779,"url":"https://github.com/jamesgober/clock-lib","last_synced_at":"2026-07-08T10:01:48.008Z","repository":{"id":359303244,"uuid":"1245351269","full_name":"jamesgober/clock-lib","owner":"jamesgober","description":"Monotonic and wall-clock time readings for Rust, with a mockable clock for deterministic testing. Simple Tier-1 API, zero dependencies, no unsafe. REPS-compliant.","archived":false,"fork":false,"pushed_at":"2026-05-21T09:45:57.000Z","size":122,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-21T15:49:46.880Z","etag":null,"topics":["clock","mock","monotonic","reps","rust","testing","time","timekeeping"],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jamesgober.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-21T06:26:39.000Z","updated_at":"2026-05-21T09:44:30.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/jamesgober/clock-lib","commit_stats":null,"previous_names":["jamesgober/clock-lib"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/jamesgober/clock-lib","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamesgober%2Fclock-lib","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamesgober%2Fclock-lib/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamesgober%2Fclock-lib/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamesgober%2Fclock-lib/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jamesgober","download_url":"https://codeload.github.com/jamesgober/clock-lib/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamesgober%2Fclock-lib/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35260671,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-08T02:00:06.796Z","response_time":61,"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","mock","monotonic","reps","rust","testing","time","timekeeping"],"created_at":"2026-07-08T10:01:47.167Z","updated_at":"2026-07-08T10:01:48.002Z","avatar_url":"https://github.com/jamesgober.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e\n    \u003cimg width=\"99\" alt=\"Rust logo\" src=\"https://raw.githubusercontent.com/jamesgober/rust-collection/72baabd71f00e14aa9184efcb16fa3deddda3a0a/assets/rust-logo.svg\"\u003e\n    \u003cbr\u003e\u003cb\u003eclock-lib\u003c/b\u003e\n    \u003cbr\u003e\u003csub\u003e\u003csup\u003eRUST TIME LIBRARY\u003c/sup\u003e\u003c/sub\u003e\n\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://crates.io/crates/clock-lib\"\u003e\u003cimg src=\"https://img.shields.io/crates/v/clock-lib.svg\" alt=\"Crates.io\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://crates.io/crates/clock-lib\" alt=\"Download\"\u003e\u003cimg alt=\"Crates.io Downloads\" src=\"https://img.shields.io/crates/d/clock-lib?color=%230099ff\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://docs.rs/clock-lib\"\u003e\u003cimg src=\"https://docs.rs/clock-lib/badge.svg\" alt=\"Documentation\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/jamesgober/clock-lib/actions\"\u003e\u003cimg alt=\"GitHub CI\" src=\"https://github.com/jamesgober/clock-lib/actions/workflows/ci.yml/badge.svg\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/rust-lang/rfcs/blob/master/text/2495-min-rust-version.md\" title=\"MSRV\"\u003e\u003cimg alt=\"MSRV\" src=\"https://img.shields.io/badge/MSRV-1.85%2B-blue\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003cb\u003eMonotonic \u0026 Wall-Clock Time, Done Right\u003c/b\u003e\n    \u003cbr\u003e\n    \u003ci\u003eSimple, fast, zero-dependency time readings with a mockable clock for deterministic testing\u003c/i\u003e\n\u003c/p\u003e\n\n\u003cp\u003e\n    \u003cstrong\u003eclock-lib\u003c/strong\u003e provides clean, correct access to the two kinds of time every program needs: \u003cb\u003emonotonic time\u003c/b\u003e for measuring durations, and \u003cb\u003ewall-clock time\u003c/b\u003e for timestamps. It draws a hard line between them at the API level, so you can never accidentally measure elapsed time with a clock that jumps backwards during an NTP sync.\n\u003c/p\u003e\n\n\u003cp\u003e\n    The headline feature is the \u003cb\u003emockable clock\u003c/b\u003e. In production, time comes from the operating system. In tests, you inject a \u003ccode\u003eManualClock\u003c/code\u003e and advance time instantly \u0026mdash; no \u003ccode\u003esleep\u003c/code\u003e, no flaky timing, fully deterministic. Every time-driven system built on \u003cstrong\u003eclock-lib\u003c/strong\u003e (rate limiters, TTL caches, timeouts, schedulers) becomes trivially testable.\n\u003c/p\u003e\n\n\u003cp\u003e\n    Built for performance and correctness: a one-line Tier-1 API for the common case, zero runtime dependencies, \u003ccode\u003e#![forbid(unsafe_code)]\u003c/code\u003e at the crate root, and \u003ccode\u003eno_std\u003c/code\u003e-compatible builds. \u003cstrong\u003eclock-lib\u003c/strong\u003e wraps \u003ccode\u003estd::time\u003c/code\u003e with a thin, well-inlined layer that \u003ca href=\"docs/PERFORMANCE.md\"\u003ebenchmarks at zero overhead\u003c/a\u003e \u0026mdash; you pay the syscall cost and nothing more.\n\u003c/p\u003e\n\n## Features\n\n### Two Kinds of Time, Clearly Separated\n- **Monotonic readings** \u0026mdash; for measuring elapsed time; never goes backwards\n- **Wall-clock readings** \u0026mdash; for timestamps and calendar time\n- **Type-level separation** \u0026mdash; the API makes it impossible to subtract a wall-clock time from a monotonic one\n\n### Mockable Clock (the killer feature)\n- **`SystemClock`** \u0026mdash; reads the OS in production\n- **`ManualClock`** \u0026mdash; advance time instantly in tests, fully deterministic\n- **`Clock` trait** \u0026mdash; inject time into any system for testability\n\n### Simple Tier-1 API\n- **`now()`** \u0026mdash; monotonic reading\n- **`elapsed(earlier)`** \u0026mdash; duration since a monotonic reading\n- **`wall()`** \u0026mdash; wall-clock reading\n- **`unix()` / `unix_ms()` / `unix_ns()`** \u0026mdash; unix time conveniences\n\n### Lean \u0026 Correct\n- **Zero runtime dependencies** \u0026mdash; wraps `std::time`\n- **`#![forbid(unsafe_code)]`** \u0026mdash; enforced by the compiler\n- **`no_std`-compatible** \u0026mdash; the crate builds against bare-metal targets with `default-features = false`\n- **Cross-platform** \u0026mdash; Linux, macOS, Windows\n\n\u003e This crate deliberately does **not** do calendar math, date formatting, or timezones. For that, use [`chrono`](https://crates.io/crates/chrono) or [`time`](https://crates.io/crates/time). clock-lib is the lean primitive layer beneath them.\n\n\u003chr\u003e\n\n## Installation\n\n```toml\n[dependencies]\nclock-lib = \"1.0\"\n```\n\nFor `no_std` builds, opt out of the default `std` feature:\n\n```toml\n[dependencies]\nclock-lib = { version = \"1.0\", default-features = false }\n```\n\nIn `no_std` mode, only the `VERSION` constant is exposed \u0026mdash; the reading APIs all require an OS clock and are gated behind the `std` feature. This is the honest cost of a portable clock library: the readings themselves are platform-specific.\n\n\u003chr\u003e\n\n## Quick Start\n\n```rust\nuse clock_lib as clock;\n\n// Measure elapsed time (monotonic — safe)\nlet start = clock::now();\n// ... do work ...\nlet took = clock::elapsed(start);\n\n// Get a timestamp (wall-clock)\nlet unix_seconds = clock::unix();\n```\n\nReach for the typed surface when you need it \u0026mdash; [`Monotonic`](https://docs.rs/clock-lib/latest/clock_lib/struct.Monotonic.html) for elapsed-time math, [`Wall`](https://docs.rs/clock-lib/latest/clock_lib/struct.Wall.html) for timestamps. The compiler refuses to mix the two, so you cannot accidentally measure an interval with a clock that can step backwards.\n\n### Deterministic Time in Tests\n\n```rust\nuse clock_lib::{Clock, ManualClock, Monotonic};\nuse std::time::Duration;\n\nfn expired\u003cC: Clock\u003e(clock: \u0026C, stamp: Monotonic, ttl: Duration) -\u003e bool {\n    clock.now().duration_since(stamp) \u003e= ttl\n}\n\nlet clock = ManualClock::new();\nlet stamp = clock.now();\nassert!(!expired(\u0026clock, stamp, Duration::from_secs(60)));\n\nclock.advance(Duration::from_secs(60));   // instant, no sleep\nassert!(expired(\u0026clock, stamp, Duration::from_secs(60)));\n```\n\nInject [`Clock`](https://docs.rs/clock-lib/latest/clock_lib/trait.Clock.html) into anything time-driven (rate limiters, TTL caches, timeouts) and your test suite drops every `thread::sleep` it had.\n\n\u003chr\u003e\n\n## Documentation\n\n- [API reference](docs/API.md) \u0026mdash; every public type, trait, and function with examples.\n- [Performance](docs/PERFORMANCE.md) \u0026mdash; benchmark methodology and the zero-overhead claim, verified.\n- [Developer guidelines](docs/GUIDELINES.md) \u0026mdash; the engineering bar this project is built to.\n- [Release notes](docs/release/) \u0026mdash; what shipped, when, and why.\n\n\u003cbr\u003e\n\n## Contributing\n\nContributions are welcome under the project's dual license. Before opening a pull request, please make sure:\n\n1. `cargo fmt --all -- --check` passes.\n2. `cargo clippy --all-targets --all-features -- -D warnings` is clean.\n3. `cargo test --all-features` passes.\n4. New public items include documentation and at least one example.\n5. The [API reference](docs/API.md) and [CHANGELOG](CHANGELOG.md) are updated alongside code changes.\n\n\u003cbr\u003e\n\n\u003c!-- LICENSE\n############################################# --\u003e\n\u003cdiv id=\"license\"\u003e\n    \u003ch2\u003eLicense\u003c/h2\u003e\n    \u003cp\u003e\u003cb\u003eclock-lib\u003c/b\u003e is \u003cb\u003edual-licensed\u003c/b\u003e under either of:\u003c/p\u003e\n    \u003cul\u003e\n        \u003cli\u003e\u003cb\u003eApache License, Version 2.0\u003c/b\u003e \u0026mdash; see \u003ca href=\"./LICENSE-APACHE\" title=\"Apache-2.0 License\"\u003eLICENSE-APACHE\u003c/a\u003e or \u003ca href=\"http://www.apache.org/licenses/LICENSE-2.0\" title=\"Apache-2.0 License\" target=\"_blank\"\u003eapache.org/licenses/LICENSE-2.0\u003c/a\u003e\u003c/li\u003e\n        \u003cli\u003e\u003cb\u003eMIT License\u003c/b\u003e \u0026mdash; see \u003ca href=\"./LICENSE-MIT\" title=\"MIT License\"\u003eLICENSE-MIT\u003c/a\u003e or \u003ca href=\"https://opensource.org/licenses/MIT\" title=\"MIT License\" target=\"_blank\"\u003eopensource.org/licenses/MIT\u003c/a\u003e\u003c/li\u003e\n    \u003c/ul\u003e\n    \u003cp\u003eat your option.\u003c/p\u003e\n    \u003cbr\u003e\n    \u003ch3\u003eContribution\u003c/h3\u003e\n    \u003cp\u003eUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in \u003cb\u003eclock-lib\u003c/b\u003e by you, as defined in the \u003cb\u003eApache-2.0 license\u003c/b\u003e, shall be \u003cb\u003edual-licensed\u003c/b\u003e as above, without any additional terms or conditions.\u003c/p\u003e\n    \u003cp\u003eUnless required by applicable law or agreed to in writing, software distributed under the Licenses is distributed on an \u003cb\u003e\"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND\u003c/b\u003e, either express or implied.\u003c/p\u003e\n\u003c/div\u003e\n\n\u003c!-- FOOT COPYRIGHT\n################################################# --\u003e\n\u003cdiv align=\"center\"\u003e\n  \u003ch2\u003e\u003c/h2\u003e\n  \u003csup\u003eCOPYRIGHT \u003csmall\u003e\u0026copy;\u003c/small\u003e 2026 \u003cstrong\u003eJAMES GOBER.\u003c/strong\u003e\u003c/sup\u003e\n\u003c/div\u003e","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjamesgober%2Fclock-lib","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjamesgober%2Fclock-lib","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjamesgober%2Fclock-lib/lists"}