From d4a55ccb17a162b6c105b74ecb85a575f3d1634d Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Wed, 24 May 2023 10:34:25 -0400 Subject: [PATCH] Implement tests for Timestamp --- emseries/src/date_time_tz.rs | 11 ++++++++--- emseries/src/types.rs | 33 ++++++++++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/emseries/src/date_time_tz.rs b/emseries/src/date_time_tz.rs index 287e2e1..447f4de 100644 --- a/emseries/src/date_time_tz.rs +++ b/emseries/src/date_time_tz.rs @@ -17,7 +17,7 @@ use chrono::SecondsFormat; use chrono_tz::Etc::UTC; use serde::de::{self, Deserialize, Deserializer, Visitor}; use serde::ser::{Serialize, Serializer}; -use std::fmt; +use std::{fmt, str::FromStr}; /// This is a wrapper around date time objects, using timezones from the chroon-tz database and /// providing string representation and parsing of the form " ", i.e., @@ -54,8 +54,12 @@ impl DateTimeTz { ) } } +} - pub fn from_str(s: &str) -> Result { +impl std::str::FromStr for DateTimeTz { + type Err = chrono::ParseError; + + fn from_str(s: &str) -> Result { let v: Vec<&str> = s.split_terminator(" ").collect(); if v.len() == 2 { let tz = v[1].parse::().unwrap(); @@ -98,11 +102,12 @@ impl<'de> Deserialize<'de> for DateTimeTz { mod test { extern crate serde_json; + use super::*; use chrono::TimeZone; use chrono_tz::America::Phoenix; use chrono_tz::Etc::UTC; use chrono_tz::US::{Arizona, Central}; - use date_time_tz::DateTimeTz; + use std::str::FromStr; #[test] fn it_creates_timestamp_with_z() { diff --git a/emseries/src/types.rs b/emseries/src/types.rs index 12a841b..af41630 100644 --- a/emseries/src/types.rs +++ b/emseries/src/types.rs @@ -44,11 +44,21 @@ pub enum EmseriesWriteError { JSONWriteError(serde_json::error::Error), } -enum TimestampFormat { +#[derive(Debug, Clone, PartialEq)] +enum Timestamp { DateTimeTz(DateTimeTz), Date(NaiveDate), } +impl str::FromStr for Timestamp { + type Err = chrono::ParseError; + fn from_str(line: &str) -> Result { + DateTimeTz::from_str(line) + .map(|dtz| Timestamp::DateTimeTz(dtz)) + .or(NaiveDate::from_str(line).map(|d| Timestamp::Date(d))) + } +} + /// Any element to be put into the database needs to be Recordable. This is the common API that /// will aid in searching and later in indexing records. pub trait Recordable { @@ -116,6 +126,7 @@ mod test { extern crate serde_json; use self::dimensioned::si::{Kilogram, KG}; + use super::*; use super::{Record, Recordable}; use chrono::TimeZone; use chrono_tz::Etc::UTC; @@ -141,10 +152,26 @@ mod test { } } + #[test] + fn timestamp_parses_datetimetz_without_timezone() { + assert_eq!( + "2003-11-10T06:00:00Z".parse::().unwrap(), + Timestamp::DateTimeTz(DateTimeTz(UTC.ymd(2003, 11, 10).and_hms(6, 0, 0))), + ); + } + + #[test] + fn timestamp_parses_date() { + assert_eq!( + "2023-11-10".parse::().unwrap(), + Timestamp::Date(NaiveDate::from_ymd_opt(2023, 11, 10).unwrap()) + ); + } + const WEIGHT_ENTRY: &str = "{\"data\":{\"weight\":77.79109,\"date\":\"2003-11-10T06:00:00.000000000000Z\"},\"id\":\"3330c5b0-783f-4919-b2c4-8169c38f65ff\"}"; #[test] - pub fn legacy_deserialization() { + fn legacy_deserialization() { let rec: Record = WEIGHT_ENTRY .parse() .expect("should successfully parse the record"); @@ -162,7 +189,7 @@ mod test { } #[test] - pub fn serialization_output() { + fn serialization_output() { let rec = WeightRecord { date: DateTimeTz(UTC.ymd(2003, 11, 10).and_hms(6, 0, 0)), weight: Weight(77.0 * KG),