use rusqlite::types::{FromSql, FromSqlResult, ToSql, ToSqlOutput, ValueRef};
use rusqlite::Result as RusqliteResult;
use serde_derive::*;
use std::fmt;
use std::time::{Duration, SystemTime, UNIX_EPOCH};
#[derive(
Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize, Default,
)]
pub struct Timestamp(pub u64);
impl Timestamp {
pub fn now() -> Self {
SystemTime::now().into()
}
#[inline]
pub fn duration_since(self, other: Timestamp) -> Option<Duration> {
SystemTime::from(self).duration_since(other.into()).ok()
}
#[inline]
pub fn checked_sub(self, d: Duration) -> Option<Timestamp> {
SystemTime::from(self).checked_sub(d).map(Timestamp::from)
}
#[inline]
pub fn checked_add(self, d: Duration) -> Option<Timestamp> {
SystemTime::from(self).checked_add(d).map(Timestamp::from)
}
pub fn as_millis(self) -> u64 {
self.0
}
pub fn as_millis_i64(self) -> i64 {
self.0 as i64
}
pub const EARLIEST: Timestamp = Timestamp(727_747_200_000);
}
impl From<Timestamp> for u64 {
#[inline]
fn from(ts: Timestamp) -> Self {
ts.0
}
}
impl From<SystemTime> for Timestamp {
#[inline]
fn from(st: SystemTime) -> Self {
let d = st.duration_since(UNIX_EPOCH).unwrap(); Timestamp((d.as_secs()) * 1000 + (u64::from(d.subsec_nanos()) / 1_000_000))
}
}
impl From<Timestamp> for SystemTime {
#[inline]
fn from(ts: Timestamp) -> Self {
UNIX_EPOCH + Duration::from_millis(ts.into())
}
}
impl From<u64> for Timestamp {
#[inline]
fn from(ts: u64) -> Self {
assert!(ts != 0);
Timestamp(ts)
}
}
impl fmt::Display for Timestamp {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl ToSql for Timestamp {
fn to_sql(&self) -> RusqliteResult<ToSqlOutput<'_>> {
Ok(ToSqlOutput::from(self.0 as i64)) }
}
impl FromSql for Timestamp {
fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
value.as_i64().map(|v| Timestamp(v as u64)) }
}