#date-time #local-time #time #date #duration #calendar

no-std time-local

使使用 time crate 的本地偏移量工作变得更加容易

2 个版本

0.4.1 2024年6月20日
0.4.0 2024年6月20日
0.3.2 2024年6月20日
0.3.1 2024年6月19日
0.3.0 2024年6月19日

#171日期和时间

Download history 342/week @ 2024-06-15 67/week @ 2024-06-22 78/week @ 2024-06-29 52/week @ 2024-07-06 4/week @ 2024-07-13 4/week @ 2024-07-27

每月下载量 68

MIT/Apache

7KB

为了获取本地时间偏移量,time 调用 libclocaltime_r 函数。类似 glibcmusllocaltime_r 实现,调用 getenv("TZ") 来获取当前 TZ 环境变量的值。不幸的是,getenv() 返回的值可能会被修改环境的调用(如 setenv()unsetenv()putenv())无效化。

例如,以下单线程应用程序存在潜在的 use-after-free 错误

char * value = getenv("KEY"); // obtain pointer
setenv("KEY", "new value"); // potential free
printf("KEY = %s", value); // potential use after free

Rust 的 std::env 模块中的函数通过锁同步对环境的访问。然而,任何外国代码(包括 libc 实现)都可以在不获取该锁的情况下修改环境。这导致了关于是否应该将 Rust 的 std::env::set_var 标记为不安全的讨论。

在假设在单线程程序中访问环境实现正确的前提下,只有在多线程程序中才可能出现问题。这就是为什么 time crate 允许你在线程数为 1 时获取 UTC 偏移量。

此 crate 为可以接受使用 UTC 偏移量的缓存的程序提供了解决方案,正是通过这种方式:在调用时缓存 UTC 偏移量。以下是一个示例

use time_local::{OffsetDateTimeExt, UtcOffsetExt};

fn main() {
    time_local::init().expect("initialization should succeed before spawning threads");

    let date = std::thread::spawn(|| {
        // We can not convert a date time to it's local representation.
        assert!(time::OffsetDateTime::now_utc()
            .to_local()
            .is_err(), "to_local should fail");
        
        // We can use the cached UTC offset computed at application startup. Note that this is computing something
        // different entirely, but it may be good enough for your application.
        time::OffsetDateTime::now_utc().to_offset(time::UtcOffset::cached_local_offset())
    })
    .join()
    .expect("thread should not panic");

    println!("{date:?}")
}

请注意,UTC偏移量取决于时区和特定的日期和时间。缓存的UTC偏移量是根据当前机器的时区和时间计算的。系统本地时间的更改以及/或环境变量TZ的更改将不会反映在缓存的UTC偏移量中,并且用于.to_local()的缓存的UTC偏移量不依赖于OffsetDateTime

有关起源信息,请参阅https://github.com/time-rs/time/issues/688#issue-2346267822

依赖项

~745KB
~13K SLoC