From ee22856cb4a04345089d7349f8c6b4b84fe1ae2e Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Mon, 17 Jun 2024 15:28:53 +0100 Subject: [PATCH] Avoid precision drop in timestamp conversions --- crates/core/src/time.rs | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/crates/core/src/time.rs b/crates/core/src/time.rs index 6cd5dd2f818..43e0d44dbf0 100644 --- a/crates/core/src/time.rs +++ b/crates/core/src/time.rs @@ -293,13 +293,35 @@ impl From> for DateTimeUtc { } impl TryFrom for DateTimeUtc { - type Error = prost_types::TimestampError; + type Error = String; fn try_from( timestamp: prost_types::Timestamp, ) -> Result { - let system_time: std::time::SystemTime = timestamp.try_into()?; - Ok(Self(system_time.into())) + let seconds = timestamp.seconds; + let nanoseconds: u32 = timestamp.nanos.try_into().map_err(|err| { + format!( + "Failed to convert prost_types::Timestamp nanos {} to u32: \ + {err}", + timestamp.nanos + ) + })?; + + let parsed = { + use chrono::format; + + let mut p = format::Parsed::new(); + + p.nanosecond = Some(nanoseconds); + p.timestamp = Some(seconds); + p + }; + + let dt = parsed.to_datetime_with_timezone(&Utc).map_err(|err| { + format!("Failed to parse {parsed:?} as a chrono::DateTime: {err}") + })?; + + Ok(Self(dt)) } } @@ -316,7 +338,7 @@ impl From for prost_types::Timestamp { impl TryFrom for DateTimeUtc { - type Error = prost_types::TimestampError; + type Error = String; fn try_from( timestamp: crate::tendermint_proto::google::protobuf::Timestamp, @@ -357,7 +379,7 @@ impl TryFrom for crate::tendermint::time::Time { } impl TryFrom for DateTimeUtc { - type Error = prost_types::TimestampError; + type Error = String; fn try_from(t: crate::tendermint::time::Time) -> Result { crate::tendermint_proto::google::protobuf::Timestamp::from(t).try_into()