From 4a66b17bd0b27ea35b8ea491c1255c69ac2d29b2 Mon Sep 17 00:00:00 2001 From: novacrazy Date: Wed, 4 Jul 2018 14:12:36 -0500 Subject: [PATCH] Add docs/tests and fix math --- src/datetime.rs | 103 +++++++++++++++++++- src/naive/datetime.rs | 216 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 302 insertions(+), 17 deletions(-) diff --git a/src/datetime.rs b/src/datetime.rs index e6da144..f1a7377 100644 --- a/src/datetime.rs +++ b/src/datetime.rs @@ -998,24 +998,117 @@ pub mod serde { } } - /// TODO + /// Ser/de to/from timestamps in milliseconds + /// + /// Intended for use with `serde`s `with` attribute. + /// + /// # Example + /// + /// ```rust + /// # // We mark this ignored so that we can test on 1.13 (which does not + /// # // support custom derive), and run tests with --ignored on beta and + /// # // nightly to actually trigger these. + /// # + /// # #[macro_use] extern crate serde_derive; + /// # #[macro_use] extern crate serde_json; + /// # extern crate chrono; + /// # use chrono::{TimeZone, DateTime, Utc}; + /// use chrono::serde::ts_milliseconds; + /// #[derive(Deserialize, Serialize)] + /// struct S { + /// #[serde(with = "ts_milliseconds")] + /// time: DateTime + /// } + /// + /// # fn example() -> Result { + /// let time = Utc.ymd(2018, 5, 17).and_hms_milli(02, 04, 59, 918); + /// let my_s = S { + /// time: time.clone(), + /// }; + /// + /// let as_string = serde_json::to_string(&my_s)?; + /// assert_eq!(as_string, r#"{"time":1526522699918}"#); + /// let my_s: S = serde_json::from_str(&as_string)?; + /// assert_eq!(my_s.time, time); + /// # Ok(my_s) + /// # } + /// # fn main() { example().unwrap(); } + /// ``` pub mod ts_milliseconds { use std::fmt; use serdelib::{ser, de}; - use {DateTime, Utc, FixedOffset}; + use {DateTime, Utc}; use offset::TimeZone; use super::serde_from; - /// TODO + /// Serialize a UTC datetime into an integer number of milliseconds since the epoch + /// + /// Intended for use with `serde`s `serialize_with` attribute. + /// + /// # Example: + /// + /// ```rust + /// # // We mark this ignored so that we can test on 1.13 (which does not + /// # // support custom derive), and run tests with --ignored on beta and + /// # // nightly to actually trigger these. + /// # + /// # #[macro_use] extern crate serde_derive; + /// # #[macro_use] extern crate serde_json; + /// # extern crate chrono; + /// # use chrono::{TimeZone, DateTime, Utc}; + /// use chrono::serde::ts_milliseconds::serialize as to_milli_ts; + /// #[derive(Serialize)] + /// struct S { + /// #[serde(serialize_with = "to_milli_ts")] + /// time: DateTime + /// } + /// + /// # fn example() -> Result { + /// let my_s = S { + /// time: Utc.ymd(2018, 5, 17).and_hms_milli(02, 04, 59, 918), + /// }; + /// let as_string = serde_json::to_string(&my_s)?; + /// assert_eq!(as_string, r#"{"time":1526522699918}"#); + /// # Ok(as_string) + /// # } + /// # fn main() { example().unwrap(); } + /// ``` pub fn serialize(dt: &DateTime, serializer: S) -> Result where S: ser::Serializer { serializer.serialize_i64(dt.timestamp_millis()) } - /// TODO + /// Deserialize a `DateTime` from a millisecond timestamp + /// + /// Intended for use with `serde`s `deserialize_with` attribute. + /// + /// # Example: + /// + /// ```rust + /// # // We mark this ignored so that we can test on 1.13 (which does not + /// # // support custom derive), and run tests with --ignored on beta and + /// # // nightly to actually trigger these. + /// # + /// # #[macro_use] extern crate serde_derive; + /// # #[macro_use] extern crate serde_json; + /// # extern crate chrono; + /// # use chrono::{DateTime, Utc}; + /// use chrono::serde::ts_milliseconds::deserialize as from_milli_ts; + /// #[derive(Deserialize)] + /// struct S { + /// #[serde(deserialize_with = "from_milli_ts")] + /// time: DateTime + /// } + /// + /// # fn example() -> Result { + /// let my_s: S = serde_json::from_str(r#"{ "time": 1526522699918 }"#)?; + /// # Ok(my_s) + /// # } + /// # fn main() { example().unwrap(); } + /// ``` pub fn deserialize<'de, D>(d: D) -> Result, D::Error> where D: de::Deserializer<'de> { @@ -1092,7 +1185,7 @@ pub mod serde { use std::fmt; use serdelib::{ser, de}; - use {DateTime, Utc, FixedOffset}; + use {DateTime, Utc}; use offset::TimeZone; use super::serde_from; diff --git a/src/naive/datetime.rs b/src/naive/datetime.rs index 865718b..0ab082f 100644 --- a/src/naive/datetime.rs +++ b/src/naive/datetime.rs @@ -1692,21 +1692,117 @@ pub mod serde { } } - /// TODO + /// Used to serialize/deserialize from nanosecond-precision timestamps + /// + /// # Example: + /// + /// ```rust + /// # // We mark this ignored so that we can test on 1.13 (which does not + /// # // support custom derive), and run tests with --ignored on beta and + /// # // nightly to actually trigger these. + /// # + /// # #[macro_use] extern crate serde_derive; + /// # extern crate serde_json; + /// # extern crate serde; + /// # extern crate chrono; + /// # use chrono::{TimeZone, NaiveDate, NaiveDateTime, Utc}; + /// use chrono::naive::serde::ts_nanoseconds; + /// #[derive(Deserialize, Serialize)] + /// struct S { + /// #[serde(with = "ts_nanoseconds")] + /// time: NaiveDateTime + /// } + /// + /// # fn example() -> Result { + /// let time = NaiveDate::from_ymd(2018, 5, 17).and_hms_nano(02, 04, 59, 918355733); + /// let my_s = S { + /// time: time.clone(), + /// }; + /// + /// let as_string = serde_json::to_string(&my_s)?; + /// assert_eq!(as_string, r#"{"time":1526522699918355733}"#); + /// let my_s: S = serde_json::from_str(&as_string)?; + /// assert_eq!(my_s.time, time); + /// # Ok(my_s) + /// # } + /// # fn main() { example().unwrap(); } + /// ``` pub mod ts_nanoseconds { use std::fmt; use serdelib::{ser, de}; use NaiveDateTime; - /// TODO + /// Serialize a UTC datetime into an integer number of nanoseconds since the epoch + /// + /// Intended for use with `serde`s `serialize_with` attribute. + /// + /// # Example: + /// + /// ```rust + /// # // We mark this ignored so that we can test on 1.13 (which does not + /// # // support custom derive), and run tests with --ignored on beta and + /// # // nightly to actually trigger these. + /// # + /// # #[macro_use] extern crate serde_derive; + /// # #[macro_use] extern crate serde_json; + /// # #[macro_use] extern crate serde; + /// # extern crate chrono; + /// # use chrono::{TimeZone, NaiveDate, NaiveDateTime, Utc}; + /// # use serde::Serialize; + /// use chrono::naive::serde::ts_nanoseconds::serialize as to_nano_ts; + /// #[derive(Serialize)] + /// struct S { + /// #[serde(serialize_with = "to_nano_ts")] + /// time: NaiveDateTime + /// } + /// + /// # fn example() -> Result { + /// let my_s = S { + /// time: NaiveDate::from_ymd(2018, 5, 17).and_hms_nano(02, 04, 59, 918355733), + /// }; + /// let as_string = serde_json::to_string(&my_s)?; + /// assert_eq!(as_string, r#"{"time":1526522699918355733}"#); + /// # Ok(as_string) + /// # } + /// # fn main() { example().unwrap(); } + /// ``` pub fn serialize(dt: &NaiveDateTime, serializer: S) -> Result where S: ser::Serializer { - serializer.serialize_i64(dt.timestamp()) + serializer.serialize_i64(dt.timestamp_nanos()) } - /// TODO + /// Deserialize a `DateTime` from a nanoseconds timestamp + /// + /// Intended for use with `serde`s `deserialize_with` attribute. + /// + /// # Example: + /// + /// ```rust + /// # // We mark this ignored so that we can test on 1.13 (which does not + /// # // support custom derive), and run tests with --ignored on beta and + /// # // nightly to actually trigger these. + /// # + /// # #[macro_use] extern crate serde_derive; + /// # #[macro_use] extern crate serde_json; + /// # extern crate serde; + /// # extern crate chrono; + /// # use chrono::{NaiveDateTime, Utc}; + /// # use serde::Deserialize; + /// use chrono::naive::serde::ts_nanoseconds::deserialize as from_nano_ts; + /// #[derive(Deserialize)] + /// struct S { + /// #[serde(deserialize_with = "from_nano_ts")] + /// time: NaiveDateTime + /// } + /// + /// # fn example() -> Result { + /// let my_s: S = serde_json::from_str(r#"{ "time": 1526522699918355733 }"#)?; + /// # Ok(my_s) + /// # } + /// # fn main() { example().unwrap(); } + /// ``` pub fn deserialize<'de, D>(d: D) -> Result where D: de::Deserializer<'de> { @@ -1741,21 +1837,117 @@ pub mod serde { } } - /// TODO + /// Used to serialize/deserialize from millisecond-precision timestamps + /// + /// # Example: + /// + /// ```rust + /// # // We mark this ignored so that we can test on 1.13 (which does not + /// # // support custom derive), and run tests with --ignored on beta and + /// # // nightly to actually trigger these. + /// # + /// # #[macro_use] extern crate serde_derive; + /// # extern crate serde_json; + /// # extern crate serde; + /// # extern crate chrono; + /// # use chrono::{TimeZone, NaiveDate, NaiveDateTime, Utc}; + /// use chrono::naive::serde::ts_milliseconds; + /// #[derive(Deserialize, Serialize)] + /// struct S { + /// #[serde(with = "ts_milliseconds")] + /// time: NaiveDateTime + /// } + /// + /// # fn example() -> Result { + /// let time = NaiveDate::from_ymd(2018, 5, 17).and_hms_milli(02, 04, 59, 918); + /// let my_s = S { + /// time: time.clone(), + /// }; + /// + /// let as_string = serde_json::to_string(&my_s)?; + /// assert_eq!(as_string, r#"{"time":1526522699918}"#); + /// let my_s: S = serde_json::from_str(&as_string)?; + /// assert_eq!(my_s.time, time); + /// # Ok(my_s) + /// # } + /// # fn main() { example().unwrap(); } + /// ``` pub mod ts_milliseconds { use std::fmt; use serdelib::{ser, de}; use NaiveDateTime; - /// TODO + /// Serialize a UTC datetime into an integer number of milliseconds since the epoch + /// + /// Intended for use with `serde`s `serialize_with` attribute. + /// + /// # Example: + /// + /// ```rust + /// # // We mark this ignored so that we can test on 1.13 (which does not + /// # // support custom derive), and run tests with --ignored on beta and + /// # // nightly to actually trigger these. + /// # + /// # #[macro_use] extern crate serde_derive; + /// # #[macro_use] extern crate serde_json; + /// # #[macro_use] extern crate serde; + /// # extern crate chrono; + /// # use chrono::{TimeZone, NaiveDate, NaiveDateTime, Utc}; + /// # use serde::Serialize; + /// use chrono::naive::serde::ts_milliseconds::serialize as to_milli_ts; + /// #[derive(Serialize)] + /// struct S { + /// #[serde(serialize_with = "to_milli_ts")] + /// time: NaiveDateTime + /// } + /// + /// # fn example() -> Result { + /// let my_s = S { + /// time: NaiveDate::from_ymd(2018, 5, 17).and_hms_milli(02, 04, 59, 918), + /// }; + /// let as_string = serde_json::to_string(&my_s)?; + /// assert_eq!(as_string, r#"{"time":1526522699918}"#); + /// # Ok(as_string) + /// # } + /// # fn main() { example().unwrap(); } + /// ``` pub fn serialize(dt: &NaiveDateTime, serializer: S) -> Result where S: ser::Serializer { - serializer.serialize_i64(dt.timestamp()) + serializer.serialize_i64(dt.timestamp_millis()) } - /// TODO + /// Deserialize a `DateTime` from a milliseconds timestamp + /// + /// Intended for use with `serde`s `deserialize_with` attribute. + /// + /// # Example: + /// + /// ```rust + /// # // We mark this ignored so that we can test on 1.13 (which does not + /// # // support custom derive), and run tests with --ignored on beta and + /// # // nightly to actually trigger these. + /// # + /// # #[macro_use] extern crate serde_derive; + /// # #[macro_use] extern crate serde_json; + /// # extern crate serde; + /// # extern crate chrono; + /// # use chrono::{NaiveDateTime, Utc}; + /// # use serde::Deserialize; + /// use chrono::naive::serde::ts_milliseconds::deserialize as from_milli_ts; + /// #[derive(Deserialize)] + /// struct S { + /// #[serde(deserialize_with = "from_milli_ts")] + /// time: NaiveDateTime + /// } + /// + /// # fn example() -> Result { + /// let my_s: S = serde_json::from_str(r#"{ "time": 1526522699918 }"#)?; + /// # Ok(my_s) + /// # } + /// # fn main() { example().unwrap(); } + /// ``` pub fn deserialize<'de, D>(d: D) -> Result where D: de::Deserializer<'de> { @@ -1775,16 +1967,16 @@ pub mod serde { fn visit_i64(self, value: i64) -> Result where E: de::Error { - NaiveDateTime::from_timestamp_opt(value / 1_000_000_000, - (value % 1_000_000_000) as u32) + NaiveDateTime::from_timestamp_opt(value / 1000, + ((value % 1000) * 1_000_000) as u32) .ok_or_else(|| E::custom(format!("value is not a legal timestamp: {}", value))) } fn visit_u64(self, value: u64) -> Result where E: de::Error { - NaiveDateTime::from_timestamp_opt(value as i64 / 1_000_000_000, - (value as i64 % 1_000_000_000) as u32) + NaiveDateTime::from_timestamp_opt((value / 1000) as i64, + ((value % 1000) * 1_000_000) as u32) .ok_or_else(|| E::custom(format!("value is not a legal timestamp: {}", value))) } }