pub use super::FullDate;
use crate::definitions::traits::{FromJson, FromJsonError};
use anyhow::anyhow;
use serde_json::Value as Json;
use time::{format_description::well_known::Rfc3339, OffsetDateTime, UtcOffset};
#[derive(Debug, Clone)]
pub struct TDate(String);
#[derive(Debug, Clone)]
pub enum TDateOrFullDate {
TDate(TDate),
FullDate(FullDate),
}
impl FromJson for TDate {
fn from_json(v: &Json) -> Result<Self, FromJsonError> {
let date_str = String::from_json(v)?;
Ok(Self(
OffsetDateTime::parse(&date_str, &Rfc3339)
.map_err(|e| anyhow!("date not in RFC3339 format: {}", e))
.map_err(FromJsonError::Parsing)?
.to_offset(UtcOffset::UTC)
.replace_millisecond(0)
.unwrap()
.format(&Rfc3339)
.unwrap(),
))
}
}
impl FromJson for TDateOrFullDate {
fn from_json(v: &Json) -> Result<Self, FromJsonError> {
if let Ok(td) = TDate::from_json(v) {
return Ok(Self::TDate(td));
}
if let Ok(fd) = FullDate::from_json(v) {
return Ok(Self::FullDate(fd));
}
Err(anyhow!("could not parse as RFC3339 date-time or full-date").into())
}
}
impl From<TDate> for ciborium::Value {
fn from(t: TDate) -> ciborium::Value {
ciborium::Value::Tag(0, Box::new(t.0.into()))
}
}
impl From<TDateOrFullDate> for ciborium::Value {
fn from(t: TDateOrFullDate) -> ciborium::Value {
match t {
TDateOrFullDate::TDate(t) => t.into(),
TDateOrFullDate::FullDate(f) => f.into(),
}
}
}