From d701bd6e697cd480d07244c5d86171df91e261f2 Mon Sep 17 00:00:00 2001 From: happysalada Date: Mon, 14 Feb 2022 17:48:22 -0500 Subject: [PATCH] time: add date struct --- src/types/external/time_date.rs | 72 +++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 src/types/external/time_date.rs diff --git a/src/types/external/time_date.rs b/src/types/external/time_date.rs new file mode 100644 index 00000000..ed57c6dc --- /dev/null +++ b/src/types/external/time_date.rs @@ -0,0 +1,72 @@ +use crate::{InputValueError, InputValueResult, Scalar, ScalarType, Value}; +use time::{format_description::FormatItem, macros::format_description, Date}; + +const DATE_FORMAT: &[FormatItem<'_>] = format_description!("[year]-[month]-[day]"); + +/// A local datetime without timezone offset. +/// +/// The input/output is a string in ISO 8601 format without timezone, including +/// subseconds. E.g. "2022-01-12T07:30:19.12345". + +#[Scalar(internal, name = "Date")] +/// ISO 8601 calendar date without timezone. +/// Format: %Y-%m-%d +/// +/// # Examples +/// +/// * `1994-11-13` +/// * `2000-02-24` +impl ScalarType for Date { + fn parse(value: Value) -> InputValueResult { + match &value { + Value::String(s) => Ok(Self::parse(s, &DATE_FORMAT)?), + _ => Err(InputValueError::expected_type(value)), + } + } + + fn to_value(&self) -> Value { + Value::String( + self.format(&DATE_FORMAT) + .unwrap_or_else(|e| panic!("Failed to format `Date`: {}", e)), + ) + } +} + +#[cfg(test)] +mod tests { + use crate::{ScalarType, Value}; + use time::{macros::date, Date}; + + #[test] + fn test_date_to_value() { + let cases = [ + (date!(1994 - 11 - 13), "1994-11-13"), + (date!(2000 - 00 - 24), "2000-00-24"), + ]; + for (value, expected) in cases { + let value = value.to_value(); + + if let Value::String(s) = value { + assert_eq!(s, expected); + } else { + panic!( + "Unexpected Value type when formatting PrimitiveDateTime: {:?}", + value + ); + } + } + } + + #[test] + fn test_date_parse() { + let cases = [ + (date!(1994 - 11 - 13), "1994-11-13"), + (date!(2000 - 00 - 24), "2000-00-24"), + ]; + for (value, expected) in cases { + let value = Value::String(value.to_string()); + let parsed = ::parse(value).unwrap(); + assert_eq!(parsed, expected); + } + } +}