qubit-clock

Thread-safe clock abstractions for Rust: monotonic clocks, mock testing, high-precision time meters, and timezone support

Rust CI Coverage Crates.io Rust License

为 Rust 提供线程安全的时钟与 sleep 抽象,包含单调时钟和模拟实现。

概述

Qubit Clock 为 Rust 应用程序提供了灵活且类型安全的时钟抽象系统。它提供强大的、线程安全的时钟实现,支持基本时间访问、高精度测量、时区处理、单调时间、可模拟 relative sleep 和测试支持。

特性

🕐 时钟抽象

时钟实现

⏱️ 时间计量器

⏲️ Sleep 抽象

🔒 线程安全

🌍 时区支持

🧪 测试支持

安装

Cargo.toml 中添加:

[dependencies]
qubit-clock = "0.8"

快速开始

基本使用

use qubit_clock::{Clock, SystemClock};

let clock = SystemClock::new();
let timestamp = clock.millis();
let time = clock.time();
println!("当前时间: {}", time);

使用时区

use qubit_clock::{Clock, ZonedClock, SystemClock, Zoned};
use chrono_tz::Asia::Shanghai;

let clock = Zoned::new(SystemClock::new(), Shanghai);
let local = clock.local_time();
println!("上海本地时间: {}", local);

使用单调时间进行性能测量

use qubit_clock::{Clock, MonotonicClock};
use std::thread;
use std::time::Duration;

let clock = MonotonicClock::new();
let start = clock.millis();

thread::sleep(Duration::from_millis(100));

let elapsed = clock.millis() - start;
println!("耗时: {} 毫秒", elapsed);

使用 MockClock 进行测试

use qubit_clock::{Clock, ControllableClock, MockClock};
use chrono::{DateTime, Duration, Utc};

let clock = MockClock::new();

// 设置到特定时间
let fixed_time = DateTime::parse_from_rfc3339(
    "2024-01-01T00:00:00Z"
).unwrap().with_timezone(&Utc);
clock.set_time(fixed_time);

assert_eq!(clock.time(), fixed_time);

// 推进时间
clock.add_duration(Duration::hours(1));
assert_eq!(clock.time(), fixed_time + Duration::hours(1));

高精度测量

use qubit_clock::{NanoClock, NanoMonotonicClock};

let clock = NanoMonotonicClock::new();
let start = clock.nanos();

// 执行一些操作
for _ in 0..1000 {
    // 一些工作
}

let elapsed = clock.nanos() - start;
println!("耗时: {} 纳秒", elapsed);

使用时间计量器测量耗时

use qubit_clock::meter::TimeMeter;
use std::thread;
use std::time::Duration;

let mut meter = TimeMeter::new();
meter.start();
thread::sleep(Duration::from_millis(100));
meter.stop();
println!("耗时: {}", meter.readable_duration());

使用统一 MockTime 测试时间逻辑

MockClockMockSleeper 都可以挂在同一个 MockTimeline 上:

use qubit_clock::{Clock, MockTime};

let mock = MockTime::unix_epoch();
let clock = mock.clock();
let start = clock.millis();

mock.advance(std::time::Duration::from_secs(30));
assert_eq!(clock.millis(), start + 30_000);
use qubit_clock::MockTime;
use qubit_clock::sleep::Sleeper;
use std::time::Duration;

let mock = MockTime::unix_epoch();
let sleeper = mock.sleeper();
let worker = sleeper.clone();
let handle = std::thread::spawn(move || {
    worker.sleep_for(Duration::from_secs(5));
});

assert!(mock.timeline().wait_for_blocked_waiters(
    qubit_clock::MockWaiterKind::Sleep,
    1,
    Duration::from_secs(1),
));
mock.advance(Duration::from_secs(5));
handle.join().expect("mock sleep should finish");

高精度时间计量器

use qubit_clock::meter::NanoTimeMeter;

let mut meter = NanoTimeMeter::new();
meter.start();

// 执行一些操作
for _ in 0..1000 {
    // 一些工作
}

meter.stop();
println!("耗时: {} 纳秒", meter.nanos());
println!("可读格式: {}", meter.readable_duration());

使用时间计量器计算速度

use qubit_clock::meter::TimeMeter;
use std::thread;
use std::time::Duration;

let mut meter = TimeMeter::new();
meter.start();

// 处理 1000 个项目
for _ in 0..1000 {
    thread::sleep(Duration::from_micros(100));
}

meter.stop();
println!("处理 1000 个项目耗时 {}", meter.readable_duration());
println!("速度: {}", meter.formatted_speed_per_second(1000));

架构

本 crate 围绕几个正交的 trait 构建:

这种设计遵循接口隔离原则,确保实现只需要提供它们实际支持的功能。

时钟实现

SystemClock

MonotonicClock

NanoMonotonicClock

MockClock

MockTimeline

MockTime

Zoned\<C\>

Sleep 实现

SystemSleeper

MockSleeper

时间计量器

TimeMeter

毫秒精度的时间计量器,用于测量耗时,具有以下特性:

输出格式示例:

NanoTimeMeter

纳秒精度的时间计量器,具有与 TimeMeter 类似的特性:

输出格式示例:

为什么不直接使用 std::time::Instant

std::time::Instant 是生产代码中测量真实耗时的正确基础工具。它单调、快速且简单:

let start = std::time::Instant::now();
// 执行工作
let elapsed = start.elapsed();

本 crate 关注的是“计时”之外的几个常见需求:

简而言之,Instant 用来测量真实流逝的时间;mock 时钟让测试中的时间可控;时间计量器把耗时测量封装成可复用、可格式化、可测试的抽象。

API 参考

Clock Trait

核心 Clock trait 提供:

NanoClock Trait

高精度时钟的扩展 trait:

ZonedClock Trait

时区支持的扩展 trait:

使用 Zoned::new(clock, tz) 为时钟指定时区。

ControllableClock Trait

可控制时钟的扩展 trait(用于测试):

Mock Time Runtime

Mock time API 位于 crate root:

Sleep Trait

Sleep API 位于 qubit_clock::sleep 下:

Sleep API 只表达 relative sleep。notification wait、condition wait 和 timeout wait 属于 qubit-lock 的 monitor 原语。

设计原则

接口隔离

本 crate 遵循接口隔离原则,为不同的能力提供独立的 trait:

这使得实现只需提供它们需要的功能,保持 API 简洁和专注。

单一职责

每个 trait 和类型都有一个明确的目的:

组合优于继承

通过包装器而不是继承来扩展功能:

零成本抽象

设计确保只为使用的功能付出代价:

测试与代码覆盖率

本项目保持全面的测试覆盖,对所有功能进行详细验证。

运行测试

# 运行所有测试
cargo test

# 运行覆盖率报告
./coverage.sh

# 生成文本格式报告
./coverage.sh text

# 运行 CI 检查(测试、lint、格式化)
./ci-check.sh

依赖项

使用场景

性能监控

use qubit_clock::meter::TimeMeter;

let mut meter = TimeMeter::new();
meter.start();

// 执行操作
process_data();

meter.stop();
log::info!("处理耗时: {}", meter.readable_duration());

可模拟 sleep 控制

use qubit_clock::MockTime;
use qubit_clock::sleep::Sleeper;
use std::time::Duration;

fn retry_once<S: Sleeper>(sleeper: &S) {
    sleeper.sleep_for(Duration::from_millis(10));
}

let mock = MockTime::unix_epoch();
let sleeper = mock.sleeper();
let worker = sleeper.clone();
let handle = std::thread::spawn(move || retry_once(&worker));

assert!(mock.timeline().wait_for_blocked_waiters(
    qubit_clock::MockWaiterKind::Sleep,
    1,
    Duration::from_secs(1),
));
mock.advance(Duration::from_millis(10));
handle.join().expect("retry should finish");

测试时间相关逻辑

use qubit_clock::{Clock, ControllableClock, MockClock};
use chrono::Duration;

#[test]
fn test_expiration() {
    let clock = MockClock::new();
    let item = Item::new(clock.clone());

    // 快进 1 小时
    clock.add_duration(Duration::hours(1));

    assert!(item.is_expired());
}

基准测试

use qubit_clock::meter::NanoTimeMeter;

let mut meter = NanoTimeMeter::new();
meter.start();

for _ in 0..10000 {
    expensive_operation();
}

meter.stop();
println!("每次操作平均耗时: {} 纳秒", meter.nanos() / 10000);

许可证

Copyright (c) 2025 - 2026. Haixing Hu.

根据 Apache 许可证 2.0 版("许可证")授权;除非遵守许可证,否则您不得使用此文件。您可以在以下位置获取许可证副本:

http://www.apache.org/licenses/LICENSE-2.0

除非适用法律要求或书面同意,否则根据许可证分发的软件按"原样"分发,不附带任何明示或暗示的担保或条件。有关许可证下的特定语言管理权限和限制,请参阅许可证。

完整的许可证文本请参阅 LICENSE

贡献

欢迎贡献!请随时提交 Pull Request。

开发指南

作者

胡海星 - Qubit Co. Ltd.

相关项目

Qubit 旗下的更多 Rust 库发布在 GitHub 组织 qubit-ltd

---

仓库地址:https://github.com/qubit-ltd/rs-clock