diff --git a/sqlx-core/src/postgres/types/interval.rs b/sqlx-core/src/postgres/types/interval.rs index 9e69d298e2..325bb71bf4 100644 --- a/sqlx-core/src/postgres/types/interval.rs +++ b/sqlx-core/src/postgres/types/interval.rs @@ -66,6 +66,9 @@ impl Encode for PgInterval { impl TryFrom for chrono::Duration { type Error = crate::Error; + /// Convert a `PgInterval` to a `chrono::Duration` + /// + /// The convertion will fail if any of the fields `days` or `months` is different to 0. fn try_from(value: PgInterval) -> crate::Result { match (value.days, value.months) { (0, 0) => Ok(Self::microseconds(value.microseconds)), @@ -80,6 +83,14 @@ impl TryFrom for chrono::Duration { impl TryFrom for PgInterval { type Error = crate::Error; + /// Convert a `chrono::Duration to a `PgInterval` + /// + /// The convertion will fail if there is a loss of precision with the nanoseconds. To do a + /// lossy conversion use `PgInterval::chrono_truncate_nanos()`. + /// + /// # Panics + /// + /// The convertion panics if there is an overflow with the microseconds or nanoseconds fn try_from(value: chrono::Duration) -> crate::Result { let microseconds = value.num_microseconds().expect("Microseconds overflow"); match value @@ -100,10 +111,60 @@ impl TryFrom for PgInterval { } } +impl PgInterval { + /// Convert a `time::Duration` object to a `PgInterval` object but truncate the remaining nanoseconds. + /// # Panics + /// + /// Panics if there is an overflow retrieving the microseconds + /// + /// # Example + /// + /// ``` + /// use sqlx_core::postgres::types::PgInterval; + /// let interval = PgInterval::time_truncate_nanos(time::Duration::seconds(3_600)); + /// assert_eq!(interval, PgInterval { months: 0, days: 0, microseconds: 3_600_000_000 }); + /// ``` + #[cfg(feature = "time")] + pub fn time_truncate_nanos(value: time::Duration) -> Self { + let microseconds = + i64::try_from(value.whole_microseconds()).expect("Microseconds overflow"); + Self { + months: 0, + days: 0, + microseconds, + } + } + + /// Convert a `chrono::Duration` object to a `PgInterval` object but truncates the remaining nanoseconds. + /// # Panics + /// + /// Panics if there is an overflow retrieving the microseconds + /// + /// # Example + /// + /// ``` + /// use sqlx_core::postgres::types::PgInterval; + /// let interval = PgInterval::chrono_truncate_nanos(chrono::Duration::seconds(3_600)); + /// assert_eq!(interval, PgInterval { months: 0, days: 0, microseconds: 3_600_000_000 }); + /// ``` + #[cfg(feature = "chrono")] + pub fn chrono_truncate_nanos(value: chrono::Duration) -> Self { + let microseconds = value.num_microseconds().expect("Microseconds overflow"); + Self { + months: 0, + days: 0, + microseconds, + } + } +} + #[cfg(feature = "time")] impl TryFrom for time::Duration { type Error = crate::Error; + /// Convert a `PgInterval` to a `time::Duration` + /// + /// The convertion will fail if any of the fields `days` or `months` is different to 0. fn try_from(value: PgInterval) -> crate::Result { match (value.days, value.months) { (0, 0) => Ok(Self::microseconds(value.microseconds)), @@ -118,6 +179,14 @@ impl TryFrom for time::Duration { impl TryFrom for PgInterval { type Error = crate::Error; + /// Convert a `time::Duration to a `PgInterval` + /// + /// The convertion will fail if there is a loss of precision with the nanoseconds. To do a + /// lossy conversion use `PgInterval::time_truncate_nanos()`. + /// + /// # Panics + /// + /// The convertion panics if there is an overflow with the microseconds fn try_from(value: time::Duration) -> crate::Result { let microseconds = i64::try_from(value.whole_microseconds()).expect("Microseconds overflow");