common: Introduce SecondsSinceUnixEpoch, MilliSecondsSinceUnixEpoch
This commit is contained in:
parent
3bdead1cf2
commit
c34d570fff
@ -13,3 +13,6 @@ pub mod presence;
|
||||
pub mod push;
|
||||
pub mod receipt;
|
||||
pub mod thirdparty;
|
||||
mod time;
|
||||
|
||||
pub use time::{MilliSecondsSinceUnixEpoch, SecondsSinceUnixEpoch};
|
||||
|
94
crates/ruma-common/src/time.rs
Normal file
94
crates/ruma-common/src/time.rs
Normal file
@ -0,0 +1,94 @@
|
||||
use js_int::UInt;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{
|
||||
convert::TryInto,
|
||||
time::{Duration, SystemTime, UNIX_EPOCH},
|
||||
};
|
||||
|
||||
/// A timestamp represented as the number of milliseconds since the unix epoch.
|
||||
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct MilliSecondsSinceUnixEpoch(pub UInt);
|
||||
|
||||
impl MilliSecondsSinceUnixEpoch {
|
||||
/// Creates a `MilliSecondsSinceUnixEpoch` from the given `SystemTime`, if it is not before the
|
||||
/// unix epoch, or too large to be represented.
|
||||
pub fn from_system_time(time: SystemTime) -> Option<Self> {
|
||||
let duration = time.duration_since(UNIX_EPOCH).ok()?;
|
||||
let millis = duration.as_millis().try_into().ok()?;
|
||||
Some(Self(millis))
|
||||
}
|
||||
|
||||
/// The current milliseconds since the unix epoch.
|
||||
pub fn now() -> Self {
|
||||
Self::from_system_time(SystemTime::now()).unwrap()
|
||||
}
|
||||
|
||||
/// Creates a `SystemTime` from `self`, if it can be represented.
|
||||
pub fn to_system_time(self) -> Option<SystemTime> {
|
||||
UNIX_EPOCH.checked_add(Duration::from_millis(self.0.into()))
|
||||
}
|
||||
}
|
||||
|
||||
/// A timestamp represented as the number of seconds since the unix epoch.
|
||||
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct SecondsSinceUnixEpoch(pub UInt);
|
||||
|
||||
impl SecondsSinceUnixEpoch {
|
||||
/// Creates a `MilliSecondsSinceUnixEpoch` from the given `SystemTime`, if it is not before the
|
||||
/// unix epoch, or too large to be represented.
|
||||
pub fn from_system_time(time: SystemTime) -> Option<Self> {
|
||||
let duration = time.duration_since(UNIX_EPOCH).ok()?;
|
||||
let millis = duration.as_secs().try_into().ok()?;
|
||||
Some(Self(millis))
|
||||
}
|
||||
|
||||
/// Creates a `SystemTime` from `self`, if it can be represented.
|
||||
pub fn to_system_time(self) -> Option<SystemTime> {
|
||||
UNIX_EPOCH.checked_add(Duration::from_secs(self.0.into()))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::time::{Duration, UNIX_EPOCH};
|
||||
|
||||
use js_int::uint;
|
||||
use matches::assert_matches;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::json;
|
||||
|
||||
use super::{MilliSecondsSinceUnixEpoch, SecondsSinceUnixEpoch};
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
struct SystemTimeTest {
|
||||
millis: MilliSecondsSinceUnixEpoch,
|
||||
secs: SecondsSinceUnixEpoch,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deserialize() {
|
||||
let json = json!({ "millis": 3000, "secs": 60 });
|
||||
|
||||
assert_matches!(
|
||||
serde_json::from_value::<SystemTimeTest>(json),
|
||||
Ok(SystemTimeTest { millis, secs })
|
||||
if millis.to_system_time() == Some(UNIX_EPOCH + Duration::from_millis(3000))
|
||||
&& secs.to_system_time() == Some(UNIX_EPOCH + Duration::from_secs(60))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn serialize() {
|
||||
let request = SystemTimeTest {
|
||||
millis: MilliSecondsSinceUnixEpoch::from_system_time(UNIX_EPOCH + Duration::new(2, 0))
|
||||
.unwrap(),
|
||||
secs: SecondsSinceUnixEpoch(uint!(0)),
|
||||
};
|
||||
assert_matches!(
|
||||
serde_json::to_value(&request),
|
||||
Ok(value) if value == json!({ "millis": 2000, "secs": 0 })
|
||||
);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user