We look at some simple seconds since epoch calculations using std::time and time crate.

088-feature-image.png
Rust: seconds since epoch – “1970-01-01 00:00:00 UTC”.

I’ve done some seconds since epoch calculations in Python before. I try to do similar calculations in Rust. This is a documentation of the code which I’ve tried out. These’re just simple calculations which enable me to understand this epoch time subject better.

❶ The first example is from Constant std::time::UNIX_EPOCH, and does not require any third party crate, and can be compiled using rustc:

Content of src/main.rs:
use std::time::{SystemTime, UNIX_EPOCH};

fn main() {
    //
    // UNIX_EPOCH: "1970-01-01 00:00:00 UTC"
    //
    match SystemTime::now().duration_since(UNIX_EPOCH) {
        Ok(n) => println!("1970-01-01 00:00:00 UTC was {} seconds ago!", n.as_secs()),
        Err(_) => panic!("SystemTime before UNIX EPOCH!"),
    }
}

On both Ubuntu 22.10 and Windows 10, the output looks like:

1970-01-01 00:00:00 UTC was 1699787014 seconds ago!

Of course, if you happen to run this example, there would be more seconds than in the reported output – we’re getting older by the seconds 😂!

The next examples require time crate. Cargo.toml is common for all examples. Its dependencies section is as follow:

...
[dependencies]
time = {version = "0.3.22", default-features = false, features = ["formatting", "macros"]}

– We’ve previously also discussed time crate in a bit more detail in this post Rust: baby step – some preliminary look at date.

❷ In this second example, I’d like to assert that if we’ve a date and time just one (1) second after the epoch, i.e. UNIX_EPOCH, then the seconds since epoch should be one (1) second.

Following is the complete working example, it’s compiled with cargo build.

Content of src/main.rs:
use time::macros::datetime;
use std::time::{SystemTime, UNIX_EPOCH};

fn main() {
    // "1970-01-01 00:00:01 UTC"
    let offset_dt = datetime!(1970-01-01 0:00:01 UTC);
    let system_time = SystemTime::from(offset_dt);

    println!("offset_dt: {:#?} \n", offset_dt);
    println!("system_time: {:#?} \n", system_time);

    match system_time.duration_since(UNIX_EPOCH) {
        Ok(n) => println!("1970-01-01 00:00:00 UTC was {} seconds ago!", n.as_secs()),
        Err(_) => panic!("SystemTime before UNIX EPOCH!"),
    }
}

My Rust version on Windows 10 and Ubuntu 22.10 are the same:

F:\rust\datetime>rustc --version
rustc 1.70.0 (90c541806 2023-05-31)

behai@hp-pavilion-15:~/rust/datetime$ rustc --version
rustc 1.70.0 (90c541806 2023-05-31)

However, the output is slightly different between the two OSes. On Windows 10:

offset_dt: 1970-01-01 0:00:01.0 +00:00:00

system_time: SystemTime {
    intervals: 116444736010000000,
}

1970-01-01 00:00:00 UTC was 1 seconds ago!

On Ubuntu 22.10:

behai@hp-pavilion-15:~/rust/datetime$ ./target/debug/datetime
offset_dt: 1970-01-01 0:00:01.0 +00:00:00

system_time: SystemTime {
    tv_sec: 1,
    tv_nsec: 0,
}

1970-01-01 00:00:00 UTC was 1 seconds ago!

However, both report one (1) second since epoch, which’s what we’ve expected.

❸ In this third example, I’d like to assert that if we’ve a date and time just one (1) second after the epoch, as in the second example then add another 1 (one) minute, then the seconds since epoch should be sixty one (61) seconds.

Content of src/main.rs:
use time::{macros::datetime, Duration};
use std::time::{SystemTime, UNIX_EPOCH};

fn main() {
    // "1970-01-01 00:00:01 UTC"
    let offset_dt = datetime!(1970-01-01 0:00:01 UTC) + Duration::minutes(1);
    let system_time = SystemTime::from(offset_dt);

    println!("offset_dt: {:#?} \n", offset_dt);
    println!("system_time: {:#?} \n", system_time);

    match system_time.duration_since(UNIX_EPOCH) {
        Ok(n) => println!("1970-01-01 00:00:00 UTC was {} seconds ago!", n.as_secs()),
        Err(_) => panic!("SystemTime before UNIX EPOCH!"),
    }
}

Output on Windows 10:

offset_dt: 1970-01-01 0:01:01.0 +00:00:00

system_time: SystemTime {
    intervals: 116444736610000000,
}

1970-01-01 00:00:00 UTC was 61 seconds ago!

Output on Ubuntu 22.10:

behai@hp-pavilion-15:~/rust/datetime$ ./target/debug/datetime
offset_dt: 1970-01-01 0:01:01.0 +00:00:00

system_time: SystemTime {
    tv_sec: 61,
    tv_nsec: 0,
}

1970-01-01 00:00:00 UTC was 61 seconds ago!

❹ In this fourth and last example, I’d like to see that if I add one (1) hour to the current UTC date time, then the seconds since epoch of the later is 1*60*60 = 3,600 (three thousand six hundred) seconds more than the former’s.

Content of src/main.rs:
use time::{OffsetDateTime, Duration};
use std::time::{SystemTime, UNIX_EPOCH};

fn main() {
    let offset_dt = OffsetDateTime::now_utc();
    let offset_dt_1_hour = offset_dt + Duration::hours(1);

    let dt_secs: u64;
    let dt_1_hour_secs: u64;

    match SystemTime::from(offset_dt).duration_since(UNIX_EPOCH) {
        Ok(n) => dt_secs = n.as_secs(),
        Err(_) => panic!("1. SystemTime before UNIX EPOCH!"),
    }

    match SystemTime::from(offset_dt_1_hour).duration_since(UNIX_EPOCH) {
        Ok(n) => dt_1_hour_secs = n.as_secs(),
        Err(_) => panic!("2. SystemTime before UNIX EPOCH!"),
    }

    println!("Seconds: {}", dt_1_hour_secs - dt_secs);    
}

And the output is as expected:

Seconds: 3600

My three (3) examples are almost puerile 😂, actually I think they are… However, they help me to understand this issue much more concretely. Puerile as they are, I still like them. I hope you find them helpful too.

For more on epoch, the following Wikipedia article is worth skimming over: Epoch (computing).

Thank you for reading and please stay safe as always.

✿✿✿

Feature image source: