use std::fmt;
use std::ops::{Add, Sub};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use crate::{DateTime, Duration};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Timestamp(i64);
impl Timestamp {
#[inline(always)]
pub fn from_millis(milliseconds: i64) -> Self {
Self(milliseconds)
}
#[inline(always)]
pub fn as_i64(self) -> i64 {
self.0
}
#[inline(always)]
pub fn add_duration(self, duration: Duration) -> Self {
Self(self.0 + duration.as_millis())
}
#[inline(always)]
pub fn sub_duration(self, duration: Duration) -> Self {
Self(self.0 - duration.as_millis())
}
}
impl From<i64> for Timestamp {
#[inline(always)]
fn from(milliseconds: i64) -> Self {
Self::from_millis(milliseconds)
}
}
impl From<DateTime> for Timestamp {
#[inline(always)]
fn from(date_time: DateTime) -> Self {
Self(date_time.as_unix_millis())
}
}
impl Add<Duration> for Timestamp {
type Output = Self;
#[inline(always)]
fn add(self, rhs: Duration) -> Self::Output {
self.add_duration(rhs)
}
}
impl Sub<Duration> for Timestamp {
type Output = Self;
#[inline(always)]
fn sub(self, rhs: Duration) -> Self::Output {
self.sub_duration(rhs)
}
}
impl Sub for Timestamp {
type Output = Duration;
#[inline(always)]
fn sub(self, rhs: Self) -> Self::Output {
Duration::from_millis(self.0 - rhs.0)
}
}
impl fmt::Display for Timestamp {
#[inline(always)]
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
DateTime::from_unix_millis(self.0).fmt(formatter)
}
}
impl Serialize for Timestamp {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
if serializer.is_human_readable() {
serializer.serialize_str(&self.to_string())
} else {
serializer.serialize_i64(self.0)
}
}
}
impl<'de> Deserialize<'de> for Timestamp {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
if deserializer.is_human_readable() {
let value = String::deserialize(deserializer)?;
DateTime::parse(&value)
.map(Self::from)
.map_err(serde::de::Error::custom)
} else {
i64::deserialize(deserializer).map(Self)
}
}
}