Time API文档

概述

mc::time 模块提供毫秒精度和秒精度的时间抽象,封装 std::chrono 并扩展 ISO 8601 字符串解析/格式化、variant 序列化等能力。核心类型包括:milliseconds(毫秒精度时长)、time_point(毫秒精度时间点)、time_point_sec(秒精度时间点,轻量替代)。

主要特性

  • 双精度支持:milliseconds + time_point 提供毫秒精度,time_point_sec 提供秒精度轻量替代
  • 直观的时长字面量:seconds(n)、minutes(n)、hours(n)、days(n) 工厂函数,可读性强
  • ISO 8601 解析与格式化:from_iso_string 解析、to_iso_string / to_string 格式化,与外部系统交互简便
  • 全方位比较与算术:所有类型均支持完整的比较运算符和 += -= + - 算术运算
  • 与 std::chrono 无缝互转:所有类型均可通过构造函数或转换运算符与 std::chrono 互操作
  • variant 序列化:三种时间类型均支持 to_variant / from_variant,可存入 variant 或通过 D-Bus 传输
  • 编译期友好:大量 constexpr 构造函数和运算符,支持编译期计算

基本用法

创建时长和进行算术运算

#include <mc/time.h>
#include <cassert>

int main()
{
    // 使用工厂函数创建时长
    mc::milliseconds timeout = mc::seconds(30);       // 30000 ms
    mc::milliseconds interval = mc::minutes(5);        // 300000 ms
    mc::milliseconds one_day = mc::days(1);            // 86400000 ms

    // 算术运算
    mc::milliseconds total = timeout + interval;       // 330000 ms
    total += mc::seconds(10);                          // 340000 ms

    // 访问原始值
    int64_t ms = total.count();                        // 340000
    int64_t sec = total.to_seconds();                  // 340

    // 与 std::chrono 互操作
    auto std_dur = std::chrono::milliseconds(500);
    mc::milliseconds mc_dur(std_dur);
    assert(mc_dur.count() == 500);

    std::chrono::seconds std_sec = mc_dur;
    assert(std_sec.count() == 0);  // 500ms → 0s(向下取整)

    return 0;
}

获取当前时间和计算时间差

#include <mc/time.h>
#include <thread>
#include <iostream>

int main()
{
    // 获取当前时间(毫秒精度)
    mc::time_point start = mc::time_point::now();

    // 模拟耗时操作
    std::this_thread::sleep_for(std::chrono::milliseconds(150));

    mc::time_point end = mc::time_point::now();

    // 计算时间差
    mc::milliseconds elapsed = end - start;
    std::cout << "耗时: " << elapsed.count() << " ms" << std::endl;

    // 比较时间点
    if (end > start) {
        std::cout << "end 在 start 之后" << std::endl;
    }

    // 时间点和时长的加减
    mc::time_point deadline = start + mc::seconds(10);  // 10秒后截止
    mc::time_point before = deadline - mc::milliseconds(500);

    return 0;
}

ISO 8601 字符串解析与格式化

#include <mc/time.h>
#include <string>
#include <iostream>

int main()
{
    // 从 ISO 8601 字符串解析
    mc::time_point tp = mc::time_point::from_iso_string("2024-06-15T08:30:00Z");
    std::cout << "解析成功: " << tp.to_string() << std::endl;

    // 格式化为 ISO 8601 字符串
    mc::time_point now = mc::time_point::now();
    mc::string_view sv = now.to_iso_string();

    // 注意:返回的 string_view 使用 thread_local 存储,
    // 跨调用或跨函数时需要复制
    std::string persistent(sv.data(), sv.size());
    std::cout << "当前时间: " << persistent << std::endl;

    return 0;
}

使用 time_point_sec 轻量时间点

#include <mc/time.h>
#include <cassert>

int main()
{
    // 默认构造为零时刻
    mc::time_point_sec epoch;
    assert(epoch.sec_since_epoch() == 0);

    // 从秒数构造
    mc::time_point_sec tp(1700000000u);

    // 获取当前时间
    mc::time_point_sec now = mc::time_point_sec::now();

    // 与 time_point 互转
    mc::time_point fine = mc::time_point::now();
    mc::time_point_sec coarse(fine);
    mc::time_point back = static_cast<mc::time_point>(coarse);

    // 秒精度算术
    mc::time_point_sec later = now + 3600u;  // 一小时后
    mc::time_point_sec earlier = now - 60u;  // 一分钟前

    // 与 milliseconds 混合运算(结果返回 time_point)
    mc::time_point result = now + mc::milliseconds(500);

    return 0;
}

API 详细说明

时长工厂函数

函数 描述 异常
seconds(int64_t s) 创建 s 秒的 milliseconds 时长 不抛异常
minutes(int64_t m) 创建 m 分钟的 milliseconds 时长 不抛异常
hours(int64_t h) 创建 h 小时的 milliseconds 时长 不抛异常
days(int64_t d) 创建 d 天的 milliseconds 时长 不抛异常

mc::milliseconds

毫秒精度时长类,内部以 int64_t 存储毫秒数。

方法/运算符 描述 异常
explicit milliseconds(int64_t count = 0) 从毫秒数构造 不抛异常
template milliseconds(const std::chrono::duration<Rep, Period>&) 从 std::chrono::duration 构造,自动转换精度 不抛异常
static constexpr milliseconds maximum() 返回最大正时长(0x7fffffffffffffff ms) 不抛异常
static constexpr milliseconds zero() 返回零时长 不抛异常
count() const 返回原始毫秒数(int64_t) 不抛异常
to_seconds() const 返回秒数(int64_t,向下取整) 不抛异常
operator std::chrono::duration<Rep, Period>() 转换为 std::chrono::duration,自动转换精度 不抛异常
operator+ operator-(友元) 时长相加减,返回新的 milliseconds 不抛异常
operator+= operator-= 原地加减 不抛异常
operator== operator!= 相等/不等比较 不抛异常
operator> operator>= operator< operator<=(友元) 全序比较 不抛异常

mc::time_point

毫秒精度时间点类,内部以 milliseconds 存储自纪元以来的时长。

方法/运算符 描述 异常
explicit time_point(milliseconds elapsed = milliseconds()) 从时长构造,默认为零时刻 不抛异常
template time_point(const std::chrono::time_point<Clock, Duration>&) 从 std::chrono::time_point 构造,自动转换精度 不抛异常
static time_point now() 获取当前时间点 不抛异常
static constexpr time_point maximum() 返回最大时间点 不抛异常
static constexpr time_point min() 返回最小时间点(零时刻) 不抛异常
static time_point from_iso_string(mc::string_view s) 从 ISO 8601 字符串解析时间点 字符串格式无效时抛出 std::invalid_argument
operator mc::string_view() 隐式转换为 ISO 8601 字符串(thread_local 存储) 不抛异常
operator std::string_view() 隐式转换为 std::string_view(thread_local 存储) 不抛异常
to_string() const 格式化为 ISO 8601 字符串(thread_local 存储) 不抛异常
to_iso_string() const 同 to_string(),格式化为 ISO 8601 字符串 不抛异常
time_since_epoch() const 返回自纪元以来的 milliseconds(const 引用) 不抛异常
sec_since_epoch() const 返回自纪元以来的秒数(uint32_t) 不抛异常
template operator std::chrono::time_point<Clock, Duration>() 转换为 std::chrono::time_point 不抛异常
operator> operator>= operator< operator<= 全序比较 不抛异常
operator== operator!= 相等/不等比较 不抛异常
operator+=(const milliseconds&) operator-=(const milliseconds&) 原地加减时长 不抛异常
operator+(const milliseconds&) operator-(const milliseconds&) 时间点 ± 时长 → 新时间点 不抛异常
operator-(const time_point&) 时间点 − 时间点 → milliseconds 时长 不抛异常

mc::time_point_sec

秒精度时间点类,内部以 uint32_t 存储自纪元以来的秒数,比 time_point 更轻量。

方法/运算符 描述 异常
constexpr time_point_sec() 默认构造为零时刻 不抛异常
constexpr explicit time_point_sec(uint32_t seconds) 从秒数构造 不抛异常
constexpr time_point_sec(const time_point& t) 从 time_point 构造(截断到秒) 不抛异常
template time_point_sec(const std::chrono::time_point<Clock, Duration>&) 从 std::chrono::time_point 构造 不抛异常
static time_point_sec now() 获取当前时间点(秒精度) 不抛异常
static constexpr time_point_sec maximum() 返回最大时间点(0xffffffff 秒) 不抛异常
static constexpr time_point_sec min() 返回最小时间点(零时刻) 不抛异常
static time_point_sec from_iso_string(mc::string_view s) 从 ISO 8601 字符串解析时间点 字符串格式无效时抛出 std::invalid_argument
sec_since_epoch() const 返回自纪元以来的秒数(uint32_t) 不抛异常
operator time_point() 转换为 time_point(毫秒精度) 不抛异常
template operator std::chrono::time_point<Clock, Duration>() 转换为 std::chrono::time_point 不抛异常
operator mc::string_view() 隐式转换为 ISO 8601 字符串(thread_local 存储) 不抛异常
operator std::string_view() 隐式转换为 std::string_view(thread_local 存储) 不抛异常
to_string() const 格式化为 ISO 8601 字符串(thread_local 存储) 不抛异常
to_iso_string() const 同 to_string(),格式化为 ISO 8601 字符串 不抛异常
operator=(const time_point&) 从 time_point 赋值(截断到秒) 不抛异常
operator> operator>= operator< operator<=(友元) 全序比较 不抛异常
operator== operator!=(友元) 相等/不等比较 不抛异常
operator+=(uint32_t) operator-=(uint32_t) 原地加减秒数 不抛异常
operator+=(milliseconds) operator-=(milliseconds) 原地加减毫秒时长(截断到秒) 不抛异常
operator+(uint32_t) operator-(uint32_t) 时间点 ± 秒数 → 新 time_point_sec 不抛异常
operator+(const milliseconds&)(友元)operator-(const milliseconds&)(友元) 时间点 ± 毫秒时长 → 新 time_point 不抛异常
operator-(const time_point_sec&)(友元) 时间点 − 时间点 → milliseconds 时长 不抛异常

variant 序列化

函数 描述 异常
to_variant(const milliseconds&, variant&) 将 milliseconds 写入 variant 不抛异常
from_variant(const variant&, milliseconds&) 从 variant 读取 milliseconds variant 类型不匹配时抛出 std::bad_variant_access
to_variant(const time_point&, variant&) 将 time_point 写入 variant 不抛异常
from_variant(const variant&, time_point&) 从 variant 读取 time_point variant 类型不匹配时抛出 std::bad_variant_access
to_variant(const time_point_sec&, variant&) 将 time_point_sec 写入 variant 不抛异常
from_variant(const variant&, time_point_sec&) 从 variant 读取 time_point_sec variant 类型不匹配时抛出 std::bad_variant_access

类型别名

别名 定义 描述
opt_time_point std::optional<time_point> 可选时间点,用于表示可能不存在的时间值

最佳实践

✅ 使用 time_point_sec 存储不关心毫秒的时间戳

// ✅ 推荐:事件记录、日志时间戳等场景用 time_point_sec,节省内存
struct AuditEntry {
    mc::time_point_sec timestamp;
    mc::string user;
    mc::string action;
};

AuditEntry entry;
entry.timestamp = mc::time_point_sec::now();
entry.user = "admin";
entry.action = "login";

✅ 复制字符串输出以避免悬空引用

// ✅ 推荐:to_string / to_iso_string 返回 thread_local string_view,
// 跨调用保存时必须复制
mc::time_point now = mc::time_point::now();
std::string iso_str(now.to_iso_string().data(), now.to_iso_string().size());
// 或直接使用隐式转换构造 std::string
std::string iso_str2(static_cast<std::string_view>(now));
store_persistent(iso_str);

❌ 不应该在时间比较中使用 count() 原始值

// ❌ 不推荐:直接用原始值比较,可读性差且容易因单位混淆出错
mc::milliseconds a = mc::seconds(5);
mc::milliseconds b = mc::seconds(3);
if (a.count() > b.count()) {
    // ...
}

// ✅ 推荐:使用运算符重载,语义清晰
if (a > b) {
    // ...
}

❌ 不应该忽略 from_iso_string 的异常

// ❌ 不推荐:未处理异常,无效输入导致程序终止
mc::time_point tp = mc::time_point::from_iso_string(user_input);

// ✅ 推荐:捕获异常,提供降级处理
mc::time_point tp;
try {
    tp = mc::time_point::from_iso_string(user_input);
} catch (const std::invalid_argument&) {
    tp = mc::time_point::now();  // 使用当前时间作为默认值
    wlog("无效的时间字符串: ${input}", ("input", user_input));
}

✅ 利用 constexpr 特性定义编译期常量

// ✅ 推荐:编译期计算,零运行时开销
constexpr mc::milliseconds DEFAULT_TIMEOUT = mc::seconds(30);
constexpr mc::milliseconds RETRY_INTERVAL = mc::minutes(5);
constexpr mc::milliseconds MAX_WAIT = mc::hours(2);

void connect()
{
    wait_for(DEFAULT_TIMEOUT);
    // ...
}

❌ 不应该在循环内反复调用 now() 做高精度计时

// ❌ 不推荐:每次迭代都调用 now() 获取系统时间,开销较大
for (auto& task : tasks) {
    mc::time_point start = mc::time_point::now();
    execute(task);
    mc::milliseconds elapsed = mc::time_point::now() - start;
    record(elapsed);
}

// ✅ 推荐:使用 steady_clock 或在循环外统一计时
mc::time_point batch_start = mc::time_point::now();
for (auto& task : tasks) {
    execute(task);
}
mc::milliseconds total = mc::time_point::now() - batch_start;