Converting between prost_types Timestamp and SystemTime

Hello all,

Is there a standardized/recommended way to convert between the protobuf-supporting Timestamp struct implemented in prost_types and std::time::SystemTime?

Timestamp implements the From<SystemTime> trait but does not offer any conversion the other way. Obviously I can have a go at manually implementing a From<Timestamp> trait for SystemTime, or perhaps Into<Timestamp, SystemTime>, but this seems like it must be a common enough requirement. I've searched around but not found anything, so can anyone advise on the best way to do this?

Thanks & best wishes,

   -- Joe

You’re looking for “into”, the reciprocal trait of From. It’s automatically implemented.

Good luck!

Thanks for the advice. I do get how the From and Into traits interact; it's just that AFAICS prost_types implements the From<SystemTime> trait for Timestamp, but there is no From<Timestamp> trait for SystemTime.

So clearly, as I suggest above, one option is to implement From<Timestamp> for SystemTime. But I'd be surprised if this hadn't been done before, so was wanting to check if I'd missed something before taking this route.

There is a TryFrom for SystemTime.

1 Like

Ah, thanks! Sorry, I'd missed that, and ran into some trouble with the issue of passing a ref. But all looks like it works now.

Anyway, I uncovered something rather interesting here. The approach I took was:

let systime = match SystemTime::try_from(timestamp) {
    Ok(systime) => systime,
    Err(duration) => UNIX_EPOCH - duration
}

... but this uncovers something interesting. Suppose that we specify a negative Timestamp:

let ts = Timestamp { seconds: -20, nanos: 999 };
let systime = match SystemTime::try_from(timestamp) {
    Ok(systime) => systime,
    Err(duration) => UNIX_EPOCH - duration
}

then we trigger the Err branch, and get out SystemTime { tv_sec: -21, tv_nsec: 999999001 }.

In other words, Timestamp treats the nanos part as effectively decimal places for the seconds value (effectively sharing its sign), whereas SystemTime treats its tv_sec and tv_nsec part as separate additions to the time epoch.

What's particularly interesting is that even though Timestamp can theoretically represent values from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z, it seems to panic when converting from a SystemTime before the start of the time epoch:

let input_systime = UNIX_EPOCH - Duration::from_secs(20);
println!("input SystemTime: {:?}", input_systime);
let ts = Timestamp::from(input_systime);
println!("Timestamp: {:?}", ts);

... generates input_systime OK but panics when converting to Timestamp:

input SystemTime: SystemTime { tv_sec: -20, tv_nsec: 0 }
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: SystemTimeError(20s)'

I'm a little bit surprised both at the subtly different expected data contents of Timestamp and SystemTime, and at the failure of conversion. I'll try to submit an issue to prost_types if I get a moment.

Looks like the Unix epoch conversion constraint has been fixed: https://github.com/danburkert/prost/pull/297/

I've reported an issue about the discrepancy between Timestamp and SystemTime interpretation of the nanos field: https://github.com/danburkert/prost/issues/327

If I have time soon I'll try to test out the master branch and implement a fix if needed.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.