1 use crate::cached_size::CachedSize; 2 use crate::well_known_types::Timestamp; 3 use crate::UnknownFields; 4 use std::time::{Duration, SystemTime}; 5 6 impl Timestamp { 7 /// Unix epoch value of timestamp. 8 pub const UNIX_EPOCH: Timestamp = Timestamp { 9 seconds: 0, 10 nanos: 0, 11 unknown_fields: UnknownFields::INIT, 12 cached_size: CachedSize::INIT, 13 }; 14 15 /// Return current time as `Timestamp`. now() -> Timestamp16 pub fn now() -> Timestamp { 17 Timestamp::from(SystemTime::now()) 18 } 19 } 20 21 /// Convert from [`Timestamp`]. 22 /// 23 /// # Panics 24 /// 25 /// This function panics if given `SystemTime` is outside of `Timestamp` range. 26 impl From<SystemTime> for Timestamp { from(time: SystemTime) -> Self27 fn from(time: SystemTime) -> Self { 28 match time.duration_since(SystemTime::UNIX_EPOCH) { 29 Ok(since_epoch) => Timestamp { 30 seconds: since_epoch.as_secs() as i64, 31 nanos: since_epoch.subsec_nanos() as i32, 32 ..Default::default() 33 }, 34 Err(e) => { 35 let before_epoch = e.duration(); 36 Timestamp { 37 seconds: -(before_epoch.as_secs() as i64) 38 - (before_epoch.subsec_nanos() != 0) as i64, 39 nanos: (1_000_000_000 - before_epoch.subsec_nanos() as i32) % 1_000_000_000, 40 ..Default::default() 41 } 42 } 43 } 44 } 45 } 46 47 /// Convert into [`SystemTime`]. 48 /// 49 /// The conversion could be lossy if `SystemTime` precision is smaller than nanoseconds. 50 /// 51 /// # Panics 52 /// 53 /// This function panics: 54 /// * if given `Timestamp` is outside of `SystemTime` range 55 /// * if `Timestamp` is malformed 56 impl Into<SystemTime> for Timestamp { into(self) -> SystemTime57 fn into(self) -> SystemTime { 58 if self.seconds >= 0 { 59 let duration = 60 Duration::from_secs(self.seconds as u64) + Duration::from_nanos(self.nanos as u64); 61 SystemTime::UNIX_EPOCH + duration 62 } else { 63 let duration = 64 Duration::from_secs(-self.seconds as u64) - Duration::from_nanos(self.nanos as u64); 65 SystemTime::UNIX_EPOCH - duration 66 } 67 } 68 } 69 70 #[cfg(test)] 71 mod test { 72 use crate::well_known_types::Timestamp; 73 use std::time::Duration; 74 use std::time::SystemTime; 75 76 #[test] from_system_time()77 fn from_system_time() { 78 fn to_from(timestamp: Timestamp, system_time: SystemTime) { 79 assert_eq!(timestamp, Timestamp::from(system_time)); 80 assert_eq!(system_time, Into::<SystemTime>::into(timestamp)); 81 } 82 83 to_from(Timestamp::UNIX_EPOCH, SystemTime::UNIX_EPOCH); 84 to_from( 85 Timestamp { 86 seconds: 0, 87 nanos: 200_000_000, 88 ..Default::default() 89 }, 90 SystemTime::UNIX_EPOCH + Duration::from_millis(200), 91 ); 92 to_from( 93 Timestamp { 94 seconds: 3, 95 nanos: 200_000_000, 96 ..Default::default() 97 }, 98 SystemTime::UNIX_EPOCH + Duration::from_millis(3_200), 99 ); 100 to_from( 101 Timestamp { 102 seconds: -1, 103 nanos: 800_000_000, 104 ..Default::default() 105 }, 106 SystemTime::UNIX_EPOCH - Duration::from_millis(200), 107 ); 108 to_from( 109 Timestamp { 110 seconds: -4, 111 nanos: 800_000_000, 112 ..Default::default() 113 }, 114 SystemTime::UNIX_EPOCH - Duration::from_millis(3_200), 115 ); 116 } 117 } 118