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

- 388,571
- 95
- 1,107
- 1,366

- 658
- 2
- 6
- 16
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.

- 5,089
- 14
- 28
-
`std::time::SystemTime` is tagged with the `Clone` trait so passing a value instead of a reference should be preferred here. – Florian Dec 04 '22 at 08:20
-
Could you explain "SystemTime may or may not be UTC"? I don't see that mentioned in the docs and [this answer](https://stackoverflow.com/a/75714786/10238) to a similar question says "SystemTime itself is completely independent of timezones." – jmcnamara Jun 10 '23 at 00:09
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:

- 388,571
- 95
- 1,107
- 1,366
-
1You can also use the following .format() string to represent something close to JavaScript's .toISOString() function: `Utc::now().format("%Y-%m-%dT%H:%M:%S%.3fZ")` to get something like this: `2022-12-29T00:00:00.000Z` Playground Link: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=7cc9bcdc4022347b8a38bd81c84df3e9 – Vince Pike Dec 29 '22 at 14:09
-
1in the latest version of chrono 0.4.23, it says here https://docs.rs/chrono/0.4.23/chrono/struct.DateTime.html#method.to_rfc3339 that its _"Available on crate features alloc or std only."_, which required me to add `features = ["alloc"]` to Cargo.toml like this: `chrono = { version = "0.4.23", default_features = false, features = ["alloc"] }` – Luke Schoen Mar 07 '23 at 01:41
-
but i got the time without SystemTime because i couldn't get it to work, i just used chrono with `let now: DateTime
= Utc::now();` and added features `features = ["alloc", "clock"]` – Luke Schoen Mar 07 '23 at 02:03
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));
}
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
.

- 2,998
- 25
- 22