#系统时钟 #TAI #单调 #日期 #GPS #Unix 时间戳 #日期时间

不依赖 std tai-time

基于 TAI 时间标准的纳秒级精度单调时钟时间戳

8 个版本

0.3.3 2024 年 6 月 13 日
0.3.2 2024 年 6 月 4 日
0.3.1 2024 年 5 月 11 日
0.3.0 2024 年 4 月 7 日
0.1.0 2024 年 3 月 26 日

#52日期和时间 类别中

Download history 29/week @ 2024-04-27 91/week @ 2024-05-04 176/week @ 2024-05-11 4/week @ 2024-05-18 48/week @ 2024-05-25 100/week @ 2024-06-01 142/week @ 2024-06-08 41/week @ 2024-06-15 19/week @ 2024-06-22 1/week @ 2024-06-29 170/week @ 2024-07-27 75/week @ 2024-08-03 12/week @ 2024-08-10

每月 257 次下载

MIT/Apache

110KB
1K SLoC

tai-time

基于 TAI 时间标准的纳秒级精度单调时钟时间戳。

Cargo Documentation License

概述

虽然 Rust 的标准库已经提供了 std::time::Instant 单调时间戳,但其绝对值是透明的。在许多科学和工程应用中,如模拟、GNSS 和同步系统,需要基于绝对时间参考的单调时间戳。

这个包为这类应用提供了相当中立的、侧重于简单性、遵循 Rust 的 std::time 习惯用法以及与 std::time::Duration 类型的互操作性的时间戳。

TaiTime 时间戳指定一个 TAI 时间点。它表示为从 1970-01-01 00:00:00 TAI 或任意任意纪元开始的 64 位有符号秒数和正数纳秒。这种时间戳格式具有许多令人期望的属性

  • 它在涉及标准 Duration 类型的算术运算中计算效率很高,该类型使用非常相似的内部分配表示法
  • 当选择 1970 纪元时(参见 MonotonicTime
    • 将 Unix 时间戳精确转换为这种时间戳是微不足道的,只需从该时间戳减去 TAI 和 UTC 时间之间的闰秒数即可
    • 它构成了 80 位 PTP IEEE-1588 时间戳的严格 96 位超集,PTP IEEE-1588 是一种广泛使用的高精度时间分配标准
    • 它与 TAI64N 时间格式实质上相似(尽管不是严格相同)
  • 使用自定义纪元,可以表示其他单调时钟,如全球定位系统时钟、伽利略系统时间时钟和北斗时间时钟(参见 GpsTimeGstTimeBdtTimeTai1958TimeTai1972Time)。

MonotonicTimeTaiTime 的别名,其纪元设置为 1970-01-01 00:00:00 TAI,在没有规定特定纪元的情况下,是推荐的戳记选择。

在存在 std 的系统中,TaiClock 可以根据单调系统时钟生成 TAI 时间戳。在支持它的平台上(目前只有 Linux),可以使用 TaiTime::now 获取本地 TAI 系统时钟时间。

用法

将其添加到您的 Cargo.toml

[dependencies]
tai-time = "0.3.3"

示例

基本用法

use tai_time::{GpsTime, MonotonicClock, MonotonicTime};

// A timestamp dated 2009-02-13 23:31:30.987654321 TAI.
// (same value as Unix timestamp for 2009-02-13 23:31:30.987654321 UTC).
let t0 = MonotonicTime::new(1_234_567_890, 987_654_321).unwrap();

// Current TAI time based on the system clock, assuming 37 leap seconds.
let clock = MonotonicClock::init_from_utc(37);
let t1 = clock.now();
println!("Current TAI time: {}", t1);

// Elapsed time between `t0` and `t1`.
let dt = t1.duration_since(t0);
println!("t1 -t0: {}s, {}ns", dt.as_secs(), dt.subsec_nanos());

// Elapsed time since `t1`.
let dt = clock.now().duration_since(t1);
println!("Elapsed: {}s, {}ns", dt.as_secs(), dt.subsec_nanos());

// Print out `t1` as a GPS timestamp.
let gps_t1: GpsTime = t1.to_tai_time().unwrap();
println!("GPS timestamp: {}s, {}ns", gps_t1.as_secs(), gps_t1.subsec_nanos());

从日期时间字段和日期时间字符串构建

use tai_time::{MonotonicTime, Tai1958Time};
let t0 = MonotonicTime::try_from_date_time(2222, 11, 11, 12, 34, 56, 789000000).unwrap();
// The `FromStr` implementation accepts date-time stamps with the format:
// [±][Y]...[Y]YYYY-MM-DD hh:mm:ss[.d[d]...[d]]
// or:
// [±][Y]...[Y]YYYY-MM-DD'T'hh:mm:ss[.d[d]...[d]]
assert_eq!("2222-11-11 12:34:56.789".parse(), Ok(t0));

格式化显示为日期时间

use tai_time::MonotonicTime;
let t0 = MonotonicTime::try_from_date_time(1234, 12, 13, 14, 15, 16, 123456000).unwrap();
assert_eq!(
    format!("{}", t0),
    "1234-12-13 14:15:16.123456"
);
assert_eq!(
    format!("{:.0}", t0),
    "1234-12-13 14:15:16"
);
assert_eq!(
    format!("{:.3}", t0),
    "1234-12-13 14:15:16.123"
);
assert_eq!(
    format!("{:.9}", t0),
    "1234-12-13 14:15:16.123456000"
);

直接从系统时钟读取 TAI 时间(仅限 Linux,需要功能 tai_clock

use tai_time::MonotonicTime;

let now = MonotonicTime::now();

println!("Current TAI time: {}", now);

设计选择和限制

在从/到 UTC 基准时间戳的转换过程中,永远不会自动计算闰秒。这是故意的:由于闰秒无法预测得很远,任何试图“隐藏”它们的存在于用户代码中的尝试都会给人以错误的安全感,并且最终会使识别新闰秒引入后的故障变得更加困难。

功能标志

支持 no-std

默认情况下,此包启用 std 功能,以访问操作系统时钟并允许转换为/从 time::SystemTime。可以通过指定 default-features = false 使其兼容 no-std

使用 chrono 功能,可以提供从/到 UTC 日期时间戳的转换方法。

TAI 系统时钟

仅在 Linux 上,可以通过激活 tai_clock 功能从系统时钟读取 TAI 时间。务必阅读有关 TaiTime::now 的可能注意事项。

序列化

TaiTime 和相关错误类型可以通过激活 serde 功能使用 serde 进行(反)序列化。

defmt 支持

激活 defmt 功能将在 TaiTime 和相关错误类型上派生 defmt::Format 特性。

许可证

此软件根据您的选择,许可为 Apache 许可证第 2 版MIT 许可证

贡献

除非您明确声明,否则根据 Apache-2.0 许可证定义的,您有意提交的任何贡献,都应如上所述双重许可,而不附加任何额外的条款或条件。

依赖关系

~0–0.9MB
~17K SLoC