@@ -187,6 +187,32 @@ impl Timestamp {
187
187
}
188
188
}
189
189
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
+
190
216
pub ( crate ) const fn encode_gregorian_timestamp (
191
217
ticks : u64 ,
192
218
counter : u16 ,
@@ -1186,3 +1212,56 @@ mod tests {
1186
1212
assert_eq ! ( ( 123 , u16 :: MAX >> 2 ) , ts. to_gregorian( ) ) ;
1187
1213
}
1188
1214
}
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