use super::*;
use std::{convert::TryFrom, fmt, ops::Sub, str::FromStr};
pub(crate) type DateTime = chrono::DateTime<chrono::Utc>;
impl fmt::Display for Timestamp {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let ce = -(62167219200 * MM)..=(253402214400 * MM);
if ce.contains(&self.0) {
if let Ok(ts) = chrono::DateTime::<chrono::Utc>::try_from(self) {
return write!(
f,
"{}",
ts.to_rfc3339_opts(chrono::SecondsFormat::AutoSi, true)
);
}
}
write!(f, "({}μs)", self.0)
}
}
impl fmt::Debug for Timestamp {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Timestamp({})", self)
}
}
impl TryFrom<String> for Timestamp {
type Error = TimestampError;
fn try_from(t: String) -> Result<Self, Self::Error> {
Timestamp::from_str(t.as_ref())
}
}
impl TryFrom<&String> for Timestamp {
type Error = TimestampError;
fn try_from(t: &String) -> Result<Self, Self::Error> {
Timestamp::from_str(t.as_ref())
}
}
impl TryFrom<&str> for Timestamp {
type Error = TimestampError;
fn try_from(t: &str) -> Result<Self, Self::Error> {
Timestamp::from_str(t)
}
}
impl From<DateTime> for Timestamp {
fn from(t: DateTime) -> Self {
std::convert::From::from(&t)
}
}
impl From<&DateTime> for Timestamp {
fn from(t: &DateTime) -> Self {
let t = t.naive_utc();
Timestamp(t.timestamp() * MM + t.timestamp_subsec_nanos() as i64 / 1000)
}
}
impl TryFrom<Timestamp> for DateTime {
type Error = TimestampError;
fn try_from(t: Timestamp) -> Result<Self, Self::Error> {
std::convert::TryFrom::try_from(&t)
}
}
impl TryFrom<&Timestamp> for DateTime {
type Error = TimestampError;
fn try_from(t: &Timestamp) -> Result<Self, Self::Error> {
let (secs, nsecs) = t.as_seconds_and_nanos();
let t = chrono::naive::NaiveDateTime::from_timestamp_opt(secs, nsecs)
.ok_or(TimestampError::Overflow)?;
Ok(chrono::DateTime::from_utc(t, chrono::Utc))
}
}
impl FromStr for Timestamp {
type Err = TimestampError;
fn from_str(t: &str) -> Result<Self, Self::Err> {
let t = chrono::DateTime::parse_from_rfc3339(t)?;
let t = chrono::DateTime::from_utc(t.naive_utc(), chrono::Utc);
Ok(t.into())
}
}
impl Timestamp {
#[cfg(feature = "now")]
pub fn now() -> Timestamp {
Timestamp::from(chrono::offset::Utc::now())
}
pub fn checked_difference_signed(&self, rhs: &Timestamp) -> Option<chrono::Duration> {
Some(chrono::Duration::microseconds(self.0.checked_sub(rhs.0)?))
}
pub fn checked_add_signed(&self, rhs: &chrono::Duration) -> Option<Timestamp> {
Some(Self(self.0.checked_add(rhs.num_microseconds()?)?))
}
pub fn checked_sub_signed(&self, rhs: &chrono::Duration) -> Option<Timestamp> {
self.checked_add_signed(&-*rhs)
}
}
impl Sub<Timestamp> for Timestamp {
type Output = TimestampResult<chrono::Duration>;
fn sub(self, rhs: Timestamp) -> Self::Output {
self.checked_difference_signed(&rhs)
.ok_or(TimestampError::Overflow)
}
}