Repository: chronotope/chrono (language: rust)

Issue:
Deserializing DateTime from unix timestamp is not implemented, despite description
The Deserialize Trait can't deserialize DateTimes from timestamps despite the error message you get. I tried tracking it down in the source code, I hope the cited references are correct.

The Deserialize Trait only calls the `deserialize_str()` function

https://github.com/chronotope/chrono/blob/f4adc28dce9a139ef17c7044e2adafde029cb17d/src/datetime/serde.rs#L75-L82

where, in spite of the `expecting()` stating it accepts **"a formatted date and time string or a unix timestamp"** it only calls the `parse()` function

https://github.com/chronotope/chrono/blob/f4adc28dce9a139ef17c7044e2adafde029cb17d/src/datetime/serde.rs#L53-L66

which in turn is implemented to only try and deserialize rfc3339 strings

https://github.com/chronotope/chrono/blob/f4adc28dce9a139ef17c7044e2adafde029cb17d/src/format/parse.rs#L523-L534


Discussion / hints:
That error message, "a formatted date and time string or a unix timestamp", seems not right indeed.

We do not really have a solution yet. There is an old PR to add deserializing from strings to the existing timestamp deserializers (https://github.com/chronotope/chrono/pull/926). And another one to add full string serialization and deserialization modules (https://github.com/chronotope/chrono/pull/1067).


Fix patch:
diff --git a/src/datetime/serde.rs b/src/datetime/serde.rs
index 5e66f5786e..6a2b8d5115 100644
--- a/src/datetime/serde.rs
+++ b/src/datetime/serde.rs
@@ -23,10 +23,12 @@ pub struct MicroSecondsTimestampVisitor;
 #[derive(Debug)]
 pub struct MilliSecondsTimestampVisitor;
 
-/// Serialize into an ISO 8601 formatted string.
+/// Serialize to an RFC 3339 formatted string
 ///
-/// See [the `serde` module](./serde/index.html) for alternate
-/// serializations.
+/// As an extension to RFC 3339 this can serialize `DateTime`s outside the range of 0-9999 years
+/// using an ISO 8601 syntax (which prepends an `-` or `+`).
+///
+/// See [the `serde` module](crate::serde) for alternate serializations.
 impl<Tz: TimeZone> ser::Serialize for DateTime<Tz> {
     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
     where
@@ -54,7 +56,7 @@ impl<'de> de::Visitor<'de> for DateTimeVisitor {
     type Value = DateTime<FixedOffset>;
 
     fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
-        formatter.write_str("a formatted date and time string or a unix timestamp")
+        formatter.write_str("an RFC 3339 formatted date and time string")
     }
 
     fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
@@ -65,13 +67,12 @@ impl<'de> de::Visitor<'de> for DateTimeVisitor {
     }
 }
 
-/// Deserialize a value that optionally includes a timezone offset in its
-/// string representation
+/// Deserialize an RFC 3339 formatted string into a `DateTime<FixedOffset>`
 ///
-/// The value to be deserialized must be an rfc3339 string.
+/// As an extension to RFC 3339 this can deserialize to `DateTime`s outside the range of 0-9999
+/// years using an ISO 8601 syntax (which prepends an `-` or `+`).
 ///
-/// See [the `serde` module](./serde/index.html) for alternate
-/// deserialization formats.
+/// See [the `serde` module](crate::serde) for alternate deserialization formats.
 impl<'de> de::Deserialize<'de> for DateTime<FixedOffset> {
     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
     where
@@ -81,12 +82,14 @@ impl<'de> de::Deserialize<'de> for DateTime<FixedOffset> {
     }
 }
 
-/// Deserialize into a UTC value
+/// Deserialize an RFC 3339 formatted string into a `DateTime<Utc>`
+///
+/// If the value contains an offset from UTC that is not zero, the value will be converted to UTC.
 ///
-/// The value to be deserialized must be an rfc3339 string.
+/// As an extension to RFC 3339 this can deserialize to `DateTime`s outside the range of 0-9999
+/// years using an ISO 8601 syntax (which prepends an `-` or `+`).
 ///
-/// See [the `serde` module](./serde/index.html) for alternate
-/// deserialization formats.
+/// See [the `serde` module](crate::serde) for alternate deserialization formats.
 impl<'de> de::Deserialize<'de> for DateTime<Utc> {
     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
     where
@@ -96,13 +99,15 @@ impl<'de> de::Deserialize<'de> for DateTime<Utc> {
     }
 }
 
-/// Deserialize a value that includes no timezone in its string
-/// representation
+/// Deserialize an RFC 3339 formatted string into a `DateTime<Local>`
+///
+/// The value will remain the same instant in UTC, but the offset will be recalculated to match
+/// that of the `Local` platform time zone.
 ///
-/// The value to be deserialized must be an rfc3339 string.
+/// As an extension to RFC 3339 this can deserialize to `DateTime`s outside the range of 0-9999
+/// years using an ISO 8601 syntax (which prepends an `-` or `+`).
 ///
-/// See [the `serde` module](./serde/index.html) for alternate
-/// serialization formats.
+/// See [the `serde` module](crate::serde) for alternate deserialization formats.
 #[cfg(feature = "clock")]
 impl<'de> de::Deserialize<'de> for DateTime<Local> {
     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
diff --git a/src/lib.rs b/src/lib.rs
index 9fe35437e4..35c728f0d0 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -614,15 +614,21 @@ pub use traits::{Datelike, Timelike};
 #[doc(hidden)]
 pub use naive::__BenchYearFlags;
 
-/// Serialization/Deserialization with serde.
+/// Serialization/Deserialization with serde
 ///
-/// This module provides default implementations for `DateTime` using the [RFC 3339][1] format and various
-/// alternatives for use with serde's [`with` annotation][2].
+/// The [`DateTime`] type has default implementations for (de)serializing to/from the [RFC 3339]
+/// format. This module provides alternatives for serializing to timestamps.
+///
+/// The alternatives are for use with serde's [`with` annotation] combined with the module name.
+/// Alternatively the individual `serialize` and `deserialize` functions in each module can be used
+/// with serde's [`serialize_with`] and [`deserialize_with`] annotations.
 ///
 /// *Available on crate feature 'serde' only.*
 ///
-/// [1]: https://tools.ietf.org/html/rfc3339
-/// [2]: https://serde.rs/field-attrs.html#with
+/// [RFC 3339]: https://tools.ietf.org/html/rfc3339
+/// [`with` annotation]: https://serde.rs/field-attrs.html#with
+/// [`serialize_with`]: https://serde.rs/field-attrs.html#serialize_with
+/// [`deserialize_with`]: https://serde.rs/field-attrs.html#deserialize_with
 #[cfg(feature = "serde")]
 pub mod serde {
     use core::fmt;
diff --git a/src/naive/datetime/serde.rs b/src/naive/datetime/serde.rs
index de8abd7dc5..45c1935d6a 100644
--- a/src/naive/datetime/serde.rs
+++ b/src/naive/datetime/serde.rs
@@ -3,10 +3,9 @@ use serde::{de, ser};
 
 use super::NaiveDateTime;
 
-/// Serialize a `NaiveDateTime` as an RFC 3339 string
+/// Serialize a `NaiveDateTime` as an ISO 8601 string
 ///
-/// See [the `serde` module](./serde/index.html) for alternate
-/// serialization formats.
+/// See [the `naive::serde` module](crate::naive::serde) for alternate serialization formats.
 impl ser::Serialize for NaiveDateTime {
     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
     where
diff --git a/src/naive/mod.rs b/src/naive/mod.rs
index 4b33a5594d..d626eb9f36 100644
--- a/src/naive/mod.rs
+++ b/src/naive/mod.rs
@@ -141,14 +141,12 @@ impl Days {
     }
 }
 
-/// Serialization/Deserialization of naive types in alternate formats
+/// Serialization/Deserialization of `NaiveDateTime` in alternate formats
 ///
-/// The various modules in here are intended to be used with serde's [`with`
-/// annotation][1] to serialize as something other than the default [RFC
-/// 3339][2] format.
+/// The various modules in here are intended to be used with serde's [`with` annotation] to
+/// serialize as something other than the default ISO 8601 format.
 ///
-/// [1]: https://serde.rs/attributes.html#field-attributes
-/// [2]: https://tools.ietf.org/html/rfc3339
+/// [`with` annotation]: https://serde.rs/field-attrs.html#with
 #[cfg(feature = "serde")]
 pub mod serde {
     pub use super::datetime::serde::*;


Test patch: