How do I convert a SystemTime to ISO 8601 in Rust?

Viewed 6911

I have a SystemTime variable and I want to get the ISO 8601 format from that date.

3 Answers

The chrono package is the right tool for the job here. SystemTime may or may not be UTC, and chrono takes care of many irritating little details.

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"
}

To customize the format differently, see the chrono::format::strftime docs.

Convert it to a chrono::DateTime then use 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

The docs explain the naming choice of the methods:

ISO 8601 allows some freedom over the syntax and RFC 3339 exercises that freedom to rigidly define a fixed format

See also:

You can also use the time crate (doc). With the latest alpha release (0.3.0-ALPHA-0) you can use format_into() method while providing a &mut impl io::Write. Alternatively, you can simply use the format() method which is also compatible with older stable releases.

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

You will have to add the formatting feature to your Cargo.toml to use format_into() (i.e. formatting on v0.3+ require the feature to be enabled).

Note that you can also specify your own strftime-like format string to format/format_into.

Related