From f0e3e0cfb183253e03b1a61ddecb7b9330d47fdb Mon Sep 17 00:00:00 2001 From: Joe Carstairs Date: Tue, 17 Sep 2024 11:28:56 +0100 Subject: Refactors backend --- backend/src/models/date_time_utc.rs | 111 ++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 backend/src/models/date_time_utc.rs (limited to 'backend/src/models/date_time_utc.rs') diff --git a/backend/src/models/date_time_utc.rs b/backend/src/models/date_time_utc.rs new file mode 100644 index 0000000..6c5dc33 --- /dev/null +++ b/backend/src/models/date_time_utc.rs @@ -0,0 +1,111 @@ +use chrono::{DateTime, Datelike, Utc}; +use diesel::{ + backend::Backend, + deserialize::{self, FromSql, FromSqlRow}, + expression::AsExpression, + serialize::{self, ToSql}, + sql_types::Text, + sqlite::Sqlite, +}; +use serde::{Deserialize, Serialize}; + +#[derive( + Eq, + PartialEq, + Ord, + PartialOrd, + Serialize, + Deserialize, + Copy, + Clone, + Debug, + AsExpression, + FromSqlRow, +)] +#[diesel(sql_type=Text)] +pub struct DateTimeUtc(DateTime); + +impl DateTimeUtc { + pub fn day_diff(&self, other: &DateTimeUtc) -> u32 { + self.0 + .num_days_from_ce() + .abs_diff(other.0.num_days_from_ce()) + } + + pub fn new(date_time_utc: DateTime) -> Self { + Self(date_time_utc) + } + + pub fn now() -> Self { + Self(Utc::now()) + } +} + +impl ToSql for DateTimeUtc { + fn to_sql<'b>( + &'b self, + out: &mut diesel::serialize::Output<'b, '_, Sqlite>, + ) -> serialize::Result { + out.set_value(self.0.to_rfc3339()); + Ok(diesel::serialize::IsNull::No) + } +} + +impl FromSql for DateTimeUtc { + fn from_sql(bytes: ::RawValue<'_>) -> deserialize::Result { + let str: String = FromSql::::from_sql(bytes)?; + let date_time = str.as_str().parse::>()?; + Ok(DateTimeUtc(date_time)) + } +} + +#[cfg(test)] +mod test { + use chrono::TimeZone; + + use super::*; + + #[test] + fn given_midnight_when_day_diff_next_midnight_less_1s_then_return_0() { + let start = DateTimeUtc::new(Utc.with_ymd_and_hms(2000, 1, 1, 0, 0, 0).unwrap().to_utc()); + let end = DateTimeUtc::new( + Utc.with_ymd_and_hms(2000, 1, 1, 23, 59, 59) + .unwrap() + .to_utc(), + ); + + let day_diff = start.day_diff(&end); + let neg_day_diff = end.day_diff(&start); + + assert_eq!(day_diff, 0); + assert_eq!(day_diff, neg_day_diff); + } + + #[test] + fn given_midnight_when_day_diff_next_midnight_then_return_1() { + let start = DateTimeUtc::new(Utc.with_ymd_and_hms(2000, 1, 1, 0, 0, 0).unwrap().to_utc()); + let end = DateTimeUtc::new(Utc.with_ymd_and_hms(2000, 1, 2, 0, 0, 0).unwrap().to_utc()); + + let day_diff = start.day_diff(&end); + let neg_day_diff = end.day_diff(&start); + + assert_eq!(day_diff, 1); + assert_eq!(day_diff, neg_day_diff); + } + + #[test] + fn given_midnight_less_1s_when_day_diff_midnight_then_return_1() { + let start = DateTimeUtc::new( + Utc.with_ymd_and_hms(2000, 1, 1, 23, 59, 59) + .unwrap() + .to_utc(), + ); + let end = DateTimeUtc::new(Utc.with_ymd_and_hms(2000, 1, 2, 0, 0, 0).unwrap().to_utc()); + + let day_diff = start.day_diff(&end); + let neg_day_diff = end.day_diff(&start); + + assert_eq!(day_diff, 1); + assert_eq!(day_diff, neg_day_diff); + } +} -- cgit v1.2.3