Search code examples
rustrust-chrono

How do I handle Unix timestamps using chrono?


I can't seem to work out how to handle Unix timestamps in Rust with chrono.

I have the following code, however the naive and therefore the datetime vars are incorrect:

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

fn main() {
    println!("Hello, world!");

    let timestamp = "1627127393230".parse::<i64>().unwrap();
    let naive = NaiveDateTime::from_timestamp(timestamp, 0);
    let datetime: DateTime<Utc> = DateTime::from_utc(naive, Utc);

    println!("timestamp: {}", timestamp);
    println!("naive: {}", naive);
    println!("datetime: {}", datetime);
}

output:

❯ cargo r
    Finished dev [unoptimized + debuginfo] target(s) in 0.01s
     Running `target/debug/utc`
Hello, world!
timestamp: 1627127393230
naive: +53531-08-13 23:27:10
datetime: +53531-08-13 23:27:10 UTC

when the correct date time for 1627127393230 is:

GMT: Saturday, July 24, 2021 11:49:53.230 AM

Can someone tell me what I am missing here?


Final solution:

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

pub fn convert(timestamp: i64)  -> DateTime<Utc> {
    let naive = NaiveDateTime::from_timestamp_opt(timestamp / 1000, (timestamp % 1000) as u32 * 1_000_000).unwrap();
    DateTime::<Utc>::from_utc(naive, Utc)
}


#[test]
fn test_timestamp() {
    let timestamp = 1627127393230;
    let ts = convert(timestamp);
    assert_eq!(ts.to_string(), "2021-07-24 11:49:53.230 UTC")
}


Solution

  • from_timestamp doesn't support milliseconds. You can put the milliseconds in the second parameter as nanoseconds. But you'll have to break it out of the timestamp.

    Check out the substring crate or do it like this:

    use chrono::{DateTime, NaiveDateTime, Utc}; 
    
    fn main() {
        let timestamp = 1627127393i64;
        let nanoseconds = 230 * 1000000;
        let datetime = DateTime::<Utc>::from_utc(NaiveDateTime::from_timestamp(timestamp, nanoseconds), Utc);
        println!("{}", datetime);
    }
    

    With the substring crate:

    use substring::Substring;
    use chrono::{DateTime, NaiveDateTime, Utc}; 
    
    fn main() {
        let timestamp = "1627127393230";
        let nanoseconds = substring(timestamp, 11, 3).parse::<i64>().unwrap() * 1000000;
        let timestamp = substring(timestamp, 1, 10).parse::<i64>().unwrap();
        let datetime = DateTime::<Utc>::from_utc(NaiveDateTime::from_timestamp(timestamp, nanoseconds), Utc);
        println!("{}", datetime);
    }