如何在Rust中将SystemTime转换为ISO 8601格式?

25

我有一个 SystemTime 变量,想要从该日期中获取 ISO 8601 格式。

3个回答

20

chrono包是处理此任务的正确工具。SystemTime可能是UTC,也可能不是,而chrono会处理许多烦人的小细节。

use chrono::prelude::{DateTime, Utc};

fn iso8601(st: &std::time::SystemTime) -> String {
    let dt: DateTime<Utc> = st.clone().into();
    format!("{}", dt.format("%+"))
    // formats like "2001-07-08T00:34:60.026490+09:30"
}

要以不同的格式进行自定义,请参见chrono::format::strftime文档。


std::time::SystemTime 标记有 Clone 特性,因此在这里传递值而不是引用应该是首选。 - Florian
你能解释一下“SystemTime可能是UTC,也可能不是UTC”吗?我在文档中没有看到这方面的提及,而对于类似问题的这个答案说“SystemTime本身与时区完全独立”。 - jmcnamara

15

将其转换为chrono::DateTime,然后使用to_rfc3339

use chrono::{DateTime, Utc}; // 0.4.15
use std::time::SystemTime;

fn main() {
    let now = SystemTime::now();
    let now: DateTime<Utc> = now.into();
    let now = now.to_rfc3339();

    println!("{}", now);
}
2020-10-01T01:47:12.746202562+00:00

文档解释了方法名的选择:

ISO 8601在语法上允许一定的自由度,而RFC 3339则利用这种自由度来严格定义固定的格式

另请参见:


1
您还可以使用以下.format()字符串来表示接近JavaScript的.toISOString()函数的内容:Utc::now().format("%Y-%m-%dT%H:%M:%S%.3fZ"),以获得类似于此的内容:2022-12-29T00:00:00.000Z Playground链接:https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=7cc9bcdc4022347b8a38bd81c84df3e9 - Vince Pike
1
在最新版的chrono 0.4.23中,文档 https://docs.rs/chrono/0.4.23/chrono/struct.DateTime.html#method.to_rfc3339 中提到它的 _"仅适用于 crate features alloc 或 std"_,这要求我像这样在 Cargo.toml 中添加 features = ["alloc"]chrono = { version = "0.4.23", default_features = false, features = ["alloc"] } - Luke Schoen
但是我没有使用SystemTime获取时间,因为我无法让它正常工作,所以我只是使用了chrono库,并添加了features = ["alloc", "clock"]。代码如下:let now: DateTime<Utc> = Utc::now(); - Luke Schoen

5
你还可以使用time箱(doc)。使用最新的alpha版本(0.3.0-ALPHA-0),您可以在提供&mut impl io :: Write 的同时使用format_into()方法。或者,您也可以直接使用format()方法,它也与旧稳定版本兼容。
use time::{
    format_description::well_known::Rfc3339, // For 0.3.0-alpha-0
    // Format::Rfc3339, // For 0.2 stable versions
    OffsetDateTime
};
use std::time::SystemTime;

fn to_rfc3339<T>(dt: T) -> String where T: Into<OffsetDateTime> {
    dt.into().format(&Rfc3339)
}

fn main() {
   let now = SystemTime::now();
   println!("{}", to_rfc3339(now));
}

Playground

可以翻译为:

{{链接1:游乐场}}


你需要在你的 Cargo.toml 中添加 formatting 特性才能使用 format_into()(即 v0.3+ 上的格式化需要启用该特性)。
请注意,你也可以指定自己的 strftime-like format 字符串来进行 format/format_into 格式化。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接