blob: 43835680ddd5c0d3268f8a43e4bf33f65c7e65c1 [file] [log] [blame]
use crate::cached_size::CachedSize;
use crate::well_known_types::Timestamp;
use crate::UnknownFields;
use std::time::{Duration, SystemTime};
impl Timestamp {
/// Unix epoch value of timestamp.
pub const UNIX_EPOCH: Timestamp = Timestamp {
seconds: 0,
nanos: 0,
unknown_fields: UnknownFields::INIT,
cached_size: CachedSize::INIT,
};
/// Return current time as `Timestamp`.
pub fn now() -> Timestamp {
Timestamp::from(SystemTime::now())
}
}
/// Convert from [`Timestamp`].
///
/// # Panics
///
/// This function panics if given `SystemTime` is outside of `Timestamp` range.
impl From<SystemTime> for Timestamp {
fn from(time: SystemTime) -> Self {
match time.duration_since(SystemTime::UNIX_EPOCH) {
Ok(since_epoch) => Timestamp {
seconds: since_epoch.as_secs() as i64,
nanos: since_epoch.subsec_nanos() as i32,
..Default::default()
},
Err(e) => {
let before_epoch = e.duration();
Timestamp {
seconds: -(before_epoch.as_secs() as i64)
- (before_epoch.subsec_nanos() != 0) as i64,
nanos: (1_000_000_000 - before_epoch.subsec_nanos() as i32) % 1_000_000_000,
..Default::default()
}
}
}
}
}
/// Convert into [`SystemTime`].
///
/// The conversion could be lossy if `SystemTime` precision is smaller than nanoseconds.
///
/// # Panics
///
/// This function panics:
/// * if given `Timestamp` is outside of `SystemTime` range
/// * if `Timestamp` is malformed
impl Into<SystemTime> for Timestamp {
fn into(self) -> SystemTime {
if self.seconds >= 0 {
let duration =
Duration::from_secs(self.seconds as u64) + Duration::from_nanos(self.nanos as u64);
SystemTime::UNIX_EPOCH + duration
} else {
let duration =
Duration::from_secs(-self.seconds as u64) - Duration::from_nanos(self.nanos as u64);
SystemTime::UNIX_EPOCH - duration
}
}
}
#[cfg(test)]
mod test {
use crate::well_known_types::Timestamp;
use std::time::Duration;
use std::time::SystemTime;
#[test]
fn from_system_time() {
fn to_from(timestamp: Timestamp, system_time: SystemTime) {
assert_eq!(timestamp, Timestamp::from(system_time));
assert_eq!(system_time, Into::<SystemTime>::into(timestamp));
}
to_from(Timestamp::UNIX_EPOCH, SystemTime::UNIX_EPOCH);
to_from(
Timestamp {
seconds: 0,
nanos: 200_000_000,
..Default::default()
},
SystemTime::UNIX_EPOCH + Duration::from_millis(200),
);
to_from(
Timestamp {
seconds: 3,
nanos: 200_000_000,
..Default::default()
},
SystemTime::UNIX_EPOCH + Duration::from_millis(3_200),
);
to_from(
Timestamp {
seconds: -1,
nanos: 800_000_000,
..Default::default()
},
SystemTime::UNIX_EPOCH - Duration::from_millis(200),
);
to_from(
Timestamp {
seconds: -4,
nanos: 800_000_000,
..Default::default()
},
SystemTime::UNIX_EPOCH - Duration::from_millis(3_200),
);
}
}