Duration in nano seconds

I'm using the Duration type with nano seconds precision. The two functions for dealing with nanosecs are as_nanos and from_nanos.

However, they have different types. as_nanos returns a u128 and from_nanos takes a u64.

It's not clear to me, what's the purpose of this difference in types. Here is an example:

use std::time::Duration;

fn main() {
    let from: u64 = 1660648301_001_001_001;
    let duration: Duration = Duration::from_nanos(from);
    dbg!(duration);
    let nanos: u128 = duration.as_nanos();
    dbg!(nanos);
}
   Compiling playground v0.0.1 (/playground)
    Finished dev [unoptimized + debuginfo] target(s) in 0.62s
     Running `target/debug/playground`
[src/main.rs:6] duration = 1660648301.001001001s
[src/main.rs:8] nanos = 1660648301001001001

Of course, this has the advantage of avoiding an overflow when adding two durations together as shown below. This the only reason why I think this might have been adopted this way.

use std::time::Duration;

fn main() {
    let dur1: u64 = 18_446_744_073_001_001_001;
    let dur2: u64 = 18_446_744_073_001_001_001;
    let duration: Duration = Duration::from_nanos(dur1) + Duration::from_nanos(dur2);
    dbg!(duration);
    let nanos: u128 = duration.as_nanos();
    dbg!(nanos);
    dbg!(nanos as u64);
}
   Compiling playground v0.0.1 (/playground)
    Finished dev [unoptimized + debuginfo] target(s) in 0.78s
     Running `target/debug/playground`
[src/main.rs:7] duration = 36893488146.002002002s
[src/main.rs:9] nanos = 36893488146002002002
[src/main.rs:10] nanos as u64 = 18446744072292450386

Still, wouldn't it make sense that the type that create a duration should be the same as the type that a duration converts into. You are going to store that duration somewhere, as a type and you'll have to do conversions both ways. It also doesn't solve the overflowing issue, it just moves it from here to the person doing the implementation.

This makes a lot of sense; there is no reason it shouldn't be able to take any unsigned int type. But we probably have to wait for default generic types to evolve the API cleanly (without breaking type inference).

One valid implementation of the duration type is to split time into a nanosecounds part and a secounds part with the secounds part being stored as a 64bit integer. This type can store all nanosecound counts up to u64::MAX, however the same is not true about u128::MAX. On the other hand, it can store durations that last for more them u64::MAX nanosecounds, so when reading out, a larger integer type (u128) must be used.

2 Likes

It was considered. It would have to be a fallible conversion to Duration (or Duration would need to grow in size).