Skip to content

Commit 6dfb4b1

Browse files
committed
Conversions between Timestamp and std::time::SystemTime
Closes #834.
1 parent 2fd9b61 commit 6dfb4b1

File tree

1 file changed

+79
-0
lines changed

1 file changed

+79
-0
lines changed

src/timestamp.rs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
190216
pub(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

Comments
 (0)