Emseries now supports both DateTimeTz and Date in the records #43
|
@ -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 "<RFC3339> <Timezone Name>", i.e.,
|
||||
|
@ -54,8 +54,12 @@ impl DateTimeTz {
|
|||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_str(s: &str) -> Result<DateTimeTz, chrono::ParseError> {
|
||||
impl std::str::FromStr for DateTimeTz {
|
||||
type Err = chrono::ParseError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let v: Vec<&str> = s.split_terminator(" ").collect();
|
||||
if v.len() == 2 {
|
||||
let tz = v[1].parse::<chrono_tz::Tz>().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() {
|
||||
|
|
|
@ -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<Self, Self::Err> {
|
||||
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::<Timestamp>().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::<Timestamp>().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<WeightRecord> = 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),
|
||||
|
|
Loading…
Reference in New Issue