diff options
| author | Joe Carstairs <me@joeac.net> | 2024-11-17 09:23:28 +0000 |
|---|---|---|
| committer | Joe Carstairs <me@joeac.net> | 2024-11-17 09:23:28 +0000 |
| commit | 1ae19eb3315c40e3f9062592c27fa76c11cf626c (patch) | |
| tree | 09d9ce380795971f4b50e1d4b0ca3c57c9e1db1a /backend/core/src/models/date_utc.rs | |
| parent | 1a494937021561595d0fb29e26fb707aef9e55de (diff) | |
Renames workspace folder
Diffstat (limited to 'backend/core/src/models/date_utc.rs')
| -rw-r--r-- | backend/core/src/models/date_utc.rs | 309 |
1 files changed, 0 insertions, 309 deletions
diff --git a/backend/core/src/models/date_utc.rs b/backend/core/src/models/date_utc.rs deleted file mode 100644 index 55d9e3f..0000000 --- a/backend/core/src/models/date_utc.rs +++ /dev/null @@ -1,309 +0,0 @@ -use std::{borrow::Borrow, fmt, str::FromStr}; - -use anyhow::{Context, Error, Result}; -use chrono::{DateTime, Datelike, NaiveDate, NaiveTime, Utc}; -use diesel::{ - backend::Backend, - deserialize::{self, FromSql, FromSqlRow}, - expression::AsExpression, - serialize::{self, ToSql}, - sql_types::Text, - sqlite::Sqlite, -}; -use serde::{Deserialize, Serialize}; - -use crate::traits::{dateable::Dateable, nowlike::Nowlike}; - -use super::datetime_utc::DatetimeUtc; - -#[derive( - Eq, - PartialEq, - Ord, - PartialOrd, - Serialize, - Deserialize, - Clone, - Debug, - AsExpression, - FromSqlRow, -)] -#[diesel(sql_type=Text)] -pub struct DateUtc { - chrono_datetime_utc: DateTime<Utc>, -} - -impl DateUtc { - pub fn from_ymd(year: i32, month: u32, day: u32) -> Result<Self> { - Ok(Self { - chrono_datetime_utc: NaiveDate::from_ymd_opt(year, month, day) - .with_context(|| format!("failed to construct date from ymd {:04}-{:02}-{:02}", year, month, day))? - .and_hms_opt(0, 0, 0).unwrap() - .and_utc() - }) - } - - pub fn with_hms(&mut self, hour: u32, min: u32, sec: u32) -> Result<DatetimeUtc> { - DatetimeUtc::from_ymd_and_hms( - self.year(), self.month(), self.day(), hour, min, sec, - ) - } - - pub fn day_diff(&self, other: &DateUtc) -> u32 { - self.chrono_datetime_utc - .num_days_from_ce() - .abs_diff(other.chrono_datetime_utc.num_days_from_ce()) - } - - fn is_day_str(str: &str) -> bool { - if str.len() != 10 { - return false; - } - for (ix, ch) in str.chars().enumerate() { - if ix == 4 || ix == 7 { - if ch != '-' { - return false; - } - } else { - if ch < '0' || ch > '9' { - return false; - } - } - } - return true; - } -} - -impl Nowlike for DateUtc { - fn now() -> Self { - let now = Utc::now(); - Self::from_ymd( - now.year(), - now.month(), - now.day(), - ).unwrap() - } -} - -impl Dateable for DateUtc { - fn year(&self) -> i32 { - self.chrono_datetime_utc.year() - } - - fn month(&self) -> u32 { - self.chrono_datetime_utc.month() - } - - fn day(&self) -> u32 { - self.chrono_datetime_utc.day() - } -} - -impl From<DatetimeUtc> for DateUtc { - fn from(datetime_utc: DatetimeUtc) -> Self { - Self { - chrono_datetime_utc: datetime_utc - .borrow() - .to_string() - .parse::<DateTime<Utc>>().unwrap() - .with_time(NaiveTime::from_hms_opt(0, 0, 0).unwrap()).unwrap(), - } - } -} - -impl<T> From<T> for DateUtc where T: Borrow<DateTime<Utc>> { - fn from(chrono_datetime_utc: T) -> Self { - Self { - chrono_datetime_utc: chrono_datetime_utc - .borrow() - .with_time(NaiveTime::from_hms_opt(0, 0, 0).unwrap()).unwrap(), - } - } -} - -impl fmt::Display for DateUtc { - /// Converts to a day string, YYYY-MM-DD, in UTC - /// Example: 10.30am 24 Oct 2024 UTC -> "2024-10-24" - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - let date_str = self.chrono_datetime_utc.to_rfc3339(); - let day_str = date_str - .split_at_checked(10) - .unwrap() - .0; - write!(f, "{}", day_str) - } -} - -impl FromStr for DateUtc { - type Err = anyhow::Error; - - /// Constructs DatetimeUtc from a day string, YYYY-MM-DD, in UTC - /// Example: "2024-10-24" -> Midnight 24 Oct 2024 UTC - fn from_str(date_str: &str) -> Result<Self> { - if !Self::is_day_str(&date_str) { - Err(Error::msg(format!("{} is not a day string in YYYY-MM-DD format", date_str))) - } else { - let mut datetime_str = String::from(date_str); - datetime_str.push_str("T00:00:00.000Z"); - Ok(Self { - chrono_datetime_utc: datetime_str.parse()?, - }) - } - } -} - -impl ToSql<Text, Sqlite> for DateUtc { - fn to_sql<'b>( - &'b self, - out: &mut diesel::serialize::Output<'b, '_, Sqlite>, - ) -> serialize::Result { - out.set_value(self.to_string()); - Ok(serialize::IsNull::No) - } -} - -impl FromSql<Text, Sqlite> for DateUtc { - fn from_sql(bytes: <Sqlite as Backend>::RawValue<'_>) -> deserialize::Result<DateUtc> { - let str = <String as FromSql<Text, Sqlite>>::from_sql(bytes)?; - Ok(str.parse()?) - } -} - -#[cfg(test)] -mod test { - use crate::traits::timeable::Timeable; - - use super::*; - - #[test] - fn when_from_ymd_then_ymd_are_as_expected() { - let date_utc = DateUtc::from_ymd(1970, 11, 23); - - assert!(date_utc.is_ok()); - let date_utc = date_utc.unwrap(); - assert_eq!(date_utc.year(), 1970); - assert_eq!(date_utc.month(), 11); - assert_eq!(date_utc.day(), 23); - } - - #[test] - fn when_from_ymd_then_to_string_as_expected() { - let date_utc = DateUtc::from_ymd(1970, 11, 23); - - assert!(date_utc.is_ok()); - assert_eq!(date_utc.unwrap().to_string(), "1970-11-23"); - } - - #[test] - fn when_from_invalid_ymd_then_err() { - let date_utc_1 = DateUtc::from_ymd(1970, 0, 23); - let date_utc_2 = DateUtc::from_ymd(1970, 13, 23); - let date_utc_3 = DateUtc::from_ymd(1970, 11, 0); - let date_utc_4 = DateUtc::from_ymd(1970, 11, 31); - let date_utc_5 = DateUtc::from_ymd(1971, 2, 29); - - assert!(date_utc_1.is_err()); - assert_eq!(date_utc_1.unwrap_err().to_string(), "failed to construct date from ymd 1970-00-23"); - assert!(date_utc_2.is_err()); - assert_eq!(date_utc_2.unwrap_err().to_string(), "failed to construct date from ymd 1970-13-23"); - assert!(date_utc_3.is_err()); - assert_eq!(date_utc_3.unwrap_err().to_string(), "failed to construct date from ymd 1970-11-00"); - assert!(date_utc_4.is_err()); - assert_eq!(date_utc_4.unwrap_err().to_string(), "failed to construct date from ymd 1970-11-31"); - assert!(date_utc_5.is_err()); - assert_eq!(date_utc_5.unwrap_err().to_string(), "failed to construct date from ymd 1971-02-29"); - } - - #[test] - fn when_from_string_then_ymd_are_as_expected() { - let date_utc: Result<DateUtc> = "1970-11-23".parse(); - - assert!(date_utc.is_ok()); - let date_utc = date_utc.unwrap(); - assert_eq!(date_utc.year(), 1970); - assert_eq!(date_utc.month(), 11); - assert_eq!(date_utc.day(), 23); - } - - #[test] - fn when_from_string_then_to_string_as_expected() { - let date_utc: Result<DateUtc> = "1970-11-23".parse(); - - assert!(date_utc.is_ok()); - assert_eq!(date_utc.unwrap().to_string(), "1970-11-23"); - } - - #[test] - fn when_from_invalid_string_then_err() { - let date_utc_1: Result<DateUtc> = "1970-00-23".parse(); - let date_utc_2: Result<DateUtc> = "1970-13-23".parse(); - let date_utc_3: Result<DateUtc> = "1970-11-0".parse(); - let date_utc_4: Result<DateUtc> = "1970-11-31".parse(); - let date_utc_5: Result<DateUtc> = "1971-02-29".parse(); - - assert!(date_utc_1.is_err()); - assert!(date_utc_2.is_err()); - assert!(date_utc_3.is_err()); - assert!(date_utc_4.is_err()); - assert!(date_utc_5.is_err()); - } - - #[test] - fn with_with_hms_then_ymd_hms_are_as_expected() { - let datetime_utc = DateUtc::from_ymd(1970, 11, 23).unwrap().with_hms(12, 55, 16); - - assert!(datetime_utc.is_ok()); - let datetime_utc = datetime_utc.unwrap(); - assert_eq!(datetime_utc.year(), 1970); - assert_eq!(datetime_utc.month(), 11); - assert_eq!(datetime_utc.day(), 23); - assert_eq!(datetime_utc.hour(), 12); - assert_eq!(datetime_utc.minute(), 55); - assert_eq!(datetime_utc.second(), 16); - } - - #[test] - fn when_with_invalid_hms_then_err() { - let datetime_utc_1 = DateUtc::from_ymd(1970, 11, 23).unwrap().with_hms(25, 0, 0); - let datetime_utc_2 = DateUtc::from_ymd(1970, 11, 23).unwrap().with_hms(0, 61, 0); - let datetime_utc_3 = DateUtc::from_ymd(1970, 11, 23).unwrap().with_hms(0, 0, 61); - - assert!(datetime_utc_1.is_err()); - assert!(datetime_utc_2.is_err()); - assert!(datetime_utc_3.is_err()); - } - - #[test] - fn when_from_datetime_utc_at_different_times_on_same_day_then_eq() { - let datetime_utc1 = DateUtc::from_ymd(1970, 11, 23).unwrap().with_hms(0, 0, 0).unwrap(); - let datetime_utc2 = DateUtc::from_ymd(1970, 11, 23).unwrap().with_hms(23, 59, 59).unwrap(); - let date_utc1 = DateUtc::from(datetime_utc1); - let date_utc2 = DateUtc::from(datetime_utc2); - - assert_eq!(date_utc1, date_utc2); - } - - #[test] - fn given_today_when_day_diff_today_then_return_0() { - let start = DateUtc::from_ymd(2000, 1, 1).unwrap(); - let end = DateUtc::from_ymd(2000, 1, 1).unwrap(); - - 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_today_when_day_diff_tomorrow_then_return_1() { - let start = DateUtc::from_ymd(2000, 1, 1).unwrap(); - let end = DateUtc::from_ymd(2000, 1, 2).unwrap(); - - 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); - } -} |
