I have a pretty simple module which handles serializing/deserializing RFC-3339 strings using serde
and chrono
. I have serde
's derive
feature enabled, and chrono
's serde
feature enabled.
My code is pretty straightforward:
pub mod rfc3339_millis_utc {
use chrono::{DateTime, FixedOffset, SecondsFormat, TimeZone, Utc};
use serde::de::{self, Visitor};
use serde::{Deserializer, Serializer};
use std::fmt::{Debug, Display, Formatter};
use std::str::FromStr;
/// Serialize a [DateTime] into an RFC-3339 timestamp in UTC with milliseconds and a postfixed
/// `Z` for the UTC timezone.
pub fn serialize<S, Z>(value: &DateTime<Z>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
Z: TimeZone,
{
serializer.serialize_str(
value
.with_timezone(&Utc)
.to_rfc3339_opts(SecondsFormat::AutoSi, true)
.as_str(),
)
}
struct Rfc3339MillisVisitor;
impl<'de> Visitor<'de> for Rfc3339MillisVisitor {
type Value = DateTime<Utc>;
fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
formatter.write_str("a timestamp in RFC-3339 format, such as 2023-10-01T12:13:14.567Z")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
match DateTime::<FixedOffset>::parse_from_rfc3339(v) {
Ok(d) => Ok(d.with_timezone(&Utc)),
Err(e) => Err(Error::new(e.to_string())),
}
}
}
#[derive(Debug)]
pub struct Error {
msg: String,
}
impl Error {
pub fn new(msg: String) -> Self {
Self { msg }
}
}
impl de::Error for Error {
fn custom<T>(msg: T) -> Self
where
T: Display,
{
Self {
msg: msg.to_string(),
}
}
}
impl std::error::Error for Error {}
impl Display for Error {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str(self.msg.as_ref())
}
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<DateTime<Utc>, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_str(Rfc3339MillisVisitor)
}
}
This doesn't make any sense to me: I've explicitly implemented serde::de::Error
for my Error
type, I've implemented std::error::Error
as well, I've provided a Display
and Debug
implementation, so I'm not sure why my Error
isn't seen as a serde::de::Error
implementation, since it is clearly implemented.
What am I doing wrong here?