use serde::de::{self, Visitor};
use serde::ser;
use std::fmt;
use std::str::FromStr;
use thiserror::Error;
use time::OffsetDateTime;
#[derive(Error, Debug)]
#[error("Invalid time: {0}")]
pub struct InvalidTimeError(String);
pub fn unix_timestamp_string_to_time(s: &str) -> Result<OffsetDateTime, InvalidTimeError> {
let i = i64::from_str(s).map_err(|_| InvalidTimeError(s.to_owned()))?;
OffsetDateTime::from_unix_timestamp(i).map_err(|_| InvalidTimeError(s.to_owned()))
}
pub fn time_to_unix_timestamp_string(t: &OffsetDateTime) -> String {
t.unix_timestamp().to_string()
}
pub fn serialize<S>(time: &OffsetDateTime, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
serializer.serialize_str(&time_to_unix_timestamp_string(time))
}
pub fn is_zero(t: &OffsetDateTime) -> bool {
t.unix_timestamp() == 0
}
struct I64Visitor;
impl<'de> Visitor<'de> for I64Visitor {
type Value = OffsetDateTime;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("an integer")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
unix_timestamp_string_to_time(value).map_err(de::Error::custom)
}
fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
where
E: de::Error,
{
OffsetDateTime::from_unix_timestamp(value)
.map_err(|_| de::Error::custom(InvalidTimeError(value.to_string())))
}
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<OffsetDateTime, D::Error>
where
D: de::Deserializer<'de>,
{
deserializer.deserialize_i64(I64Visitor)
}