21

I'm using the chrono crate; after some digging I discovered the DateTime type has a function timestamp() which could generate epoch time of type i64. However, I couldn't find out how to convert it back to DateTime.

extern crate chrono;
use chrono::*;

fn main() {
    let date = chrono::UTC.ymd(2020, 1, 1).and_hms(0, 0, 0);
    println!("{}", start_date.timestamp());
    // ...how to convert it back?
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Sajuuk
  • 2,667
  • 3
  • 22
  • 34

3 Answers3

16

You first need to create a NaiveDateTime and then use it to create a DateTime again:

extern crate chrono;
use chrono::prelude::*;

fn main() {
    let datetime = Utc.ymd(2020, 1, 1).and_hms(0, 0, 0);
    let timestamp = datetime.timestamp();
    let naive_datetime = NaiveDateTime::from_timestamp(timestamp, 0);
    let datetime_again: DateTime<Utc> = DateTime::from_utc(naive_datetime, Utc);

    println!("{}", datetime_again);
}

Playground

Wes
  • 2,166
  • 1
  • 20
  • 22
ljedrz
  • 20,316
  • 4
  • 69
  • 97
  • 2
    I managed to find a similar usage in [thisplace](https://docs.rs/chrono/*/src/chrono/datetime.rs.html#42), but apparently your answer is more concise and friendly. thank you! – Sajuuk Mar 03 '17 at 07:43
  • 2021 answer at the bottom https://stackoverflow.com/a/70058251/3458484 – Aiyion.Prime Nov 21 '21 at 20:19
4

Not sure if I'm missing something, or chrono expanded its feature set in the meantime, but its 2021 and at least since chrono 0.4.0 there appears to be a cleaner way to do it:

https://docs.rs/chrono/0.4.19/chrono/#conversion-from-and-to-epoch-timestamps

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

// Construct a datetime from epoch:
let dt = Utc.timestamp(1_500_000_000, 0);
assert_eq!(dt.to_rfc2822(), "Fri, 14 Jul 2017 02:40:00 +0000");

// Get epoch value from a datetime:
let dt = DateTime::parse_from_rfc2822("Fri, 14 Jul 2017 02:40:00 +0000").unwrap();
assert_eq!(dt.timestamp(), 1_500_000_000);

So your full conversion should look like this:

extern crate chrono;
use chrono::*;

fn main() {
    let start_date = chrono::Utc.ymd(2020, 1, 1).and_hms(0, 0, 0);
    let ts = start_date.timestamp();
    println!("{}", &ts);
    let end_date = Utc.timestamp(ts, 0);
    assert_eq!(end_date, start_date);
}
Aiyion.Prime
  • 973
  • 9
  • 20
2

You can use the parse_duration crate: https://docs.rs/parse_duration/2.1.0/parse_duration/

extern crate parse_duration;
use parse_duration::parse;
use std::time::Duration;

fn main() {
    // 1587971749 seconds since UNIX_EPOCH
    assert_eq!(parse("1587971749"), Ok(Duration::new(1587971749, 0)));

    // One hour less than a day
    assert_eq!(parse("1 day -1 hour"), Ok(Duration::new(82_800, 0)));

    // Using exponents
    assert_eq!(
        parse("1.26e-1 days"),
        Ok(Duration::new(10_886, 400_000_000))
    );

    // Extra things will be ignored
    assert_eq!(
        parse("Duration: 1 hour, 15 minutes and 29 seconds"),
        Ok(Duration::new(4529, 0))
    );
}
Evandro Coan
  • 8,560
  • 11
  • 83
  • 144