@@ -187,6 +187,32 @@ impl Timestamp {
187187 }
188188}
189189
190+ #[ cfg( all( feature = "std" , not( miri) ) ) ]
191+ impl std:: convert:: TryFrom < std:: time:: SystemTime > for Timestamp {
192+ type Error = std:: time:: SystemTimeError ;
193+
194+ /// If the system time is before the Unix epoch then an error is returned.
195+ fn try_from ( st : std:: time:: SystemTime ) -> Result < Self , Self :: Error > {
196+ let dur = st. duration_since ( std:: time:: UNIX_EPOCH ) ?;
197+
198+ Ok ( Self :: from_unix_time (
199+ dur. as_secs ( ) ,
200+ dur. subsec_nanos ( ) ,
201+ 0 ,
202+ 0 ,
203+ ) )
204+ }
205+ }
206+
207+ #[ cfg( all( feature = "std" , not( miri) ) ) ]
208+ impl From < Timestamp > for std:: time:: SystemTime {
209+ fn from ( ts : Timestamp ) -> Self {
210+ let ( seconds, subsec_nanos) = ts. to_unix ( ) ;
211+
212+ Self :: UNIX_EPOCH + std:: time:: Duration :: new ( seconds, subsec_nanos)
213+ }
214+ }
215+
190216pub ( crate ) const fn encode_gregorian_timestamp (
191217 ticks : u64 ,
192218 counter : u16 ,
@@ -1186,3 +1212,56 @@ mod tests {
11861212 assert_eq ! ( ( 123 , u16 :: MAX >> 2 ) , ts. to_gregorian( ) ) ;
11871213 }
11881214}
1215+
1216+ /// Tests for conversion between `std::time::SystemTime` and `Timestamp`.
1217+ #[ cfg( all( test, feature = "std" , not( miri) ) ) ]
1218+ mod test_conversion {
1219+ use std:: {
1220+ convert:: { TryFrom , TryInto } ,
1221+ time:: { Duration , SystemTime } ,
1222+ } ;
1223+
1224+ use super :: Timestamp ;
1225+
1226+ // Components of an arbitrary timestamp with non-zero nanoseconds.
1227+ const KNOWN_SECONDS : u64 = 1_501_520_400 ;
1228+ const KNOWN_NANOS : u32 = 1_000 ;
1229+
1230+ fn known_system_time ( ) -> SystemTime {
1231+ SystemTime :: UNIX_EPOCH
1232+ . checked_add ( Duration :: new ( KNOWN_SECONDS , KNOWN_NANOS ) )
1233+ . unwrap ( )
1234+ }
1235+
1236+ fn known_timestamp ( ) -> Timestamp {
1237+ Timestamp :: from_unix_time ( KNOWN_SECONDS , KNOWN_NANOS , 0 , 0 )
1238+ }
1239+
1240+ #[ test]
1241+ fn to_system_time ( ) {
1242+ let st: SystemTime = known_timestamp ( ) . into ( ) ;
1243+
1244+ assert_eq ! ( known_system_time( ) , st) ;
1245+ }
1246+
1247+ #[ test]
1248+ fn from_system_time ( ) {
1249+ let ts: Timestamp = known_system_time ( ) . try_into ( ) . unwrap ( ) ;
1250+
1251+ assert_eq ! ( known_timestamp( ) , ts) ;
1252+ }
1253+
1254+ #[ test]
1255+ fn from_system_time_before_epoch ( ) {
1256+ let before_epoch = match SystemTime :: UNIX_EPOCH . checked_sub ( Duration :: from_nanos ( 1_000 ) ) {
1257+ Some ( st) => st,
1258+ None => {
1259+ println ! ( "SystemTime before UNIX_EPOCH is not supported on this platform" ) ;
1260+ return ;
1261+ }
1262+ } ;
1263+
1264+ Timestamp :: try_from ( before_epoch)
1265+ . expect_err ( "Timestamp should not be created from before epoch" ) ;
1266+ }
1267+ }
0 commit comments