diff options
| author | Joe Carstairs <me@joeac.net> | 2025-08-16 07:46:21 +0100 |
|---|---|---|
| committer | Joe Carstairs <me@joeac.net> | 2025-08-16 18:22:47 +0100 |
| commit | d082a30de6a0cbd1fbe2ab5a4316db0891004129 (patch) | |
| tree | c097414625e1948116383406d894842fccc98227 /schist_core/schist_models/src | |
| parent | 9c0bc43bf0b83828d9bdf8005fcccbc33dcf4171 (diff) | |
refactor models and traits with pub use
Diffstat (limited to 'schist_core/schist_models/src')
| -rw-r--r-- | schist_core/schist_models/src/date_utc.rs | 162 | ||||
| -rw-r--r-- | schist_core/schist_models/src/datetime_utc.rs | 99 | ||||
| -rw-r--r-- | schist_core/schist_models/src/lib.rs | 32 |
3 files changed, 205 insertions, 88 deletions
diff --git a/schist_core/schist_models/src/date_utc.rs b/schist_core/schist_models/src/date_utc.rs index 2b36ec0..18a894b 100644 --- a/schist_core/schist_models/src/date_utc.rs +++ b/schist_core/schist_models/src/date_utc.rs @@ -12,7 +12,7 @@ use diesel::{ }; use serde::{Deserialize, Serialize}; -use schist_traits::{dateable::Dateable, nowlike::Nowlike}; +use schist_traits::{Dateable, Nowlike}; use crate::datetime_utc::DatetimeUtc; @@ -38,16 +38,20 @@ 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() + .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, - ) + DatetimeUtc::from_ymd_and_hms(self.year(), self.month(), self.day(), hour, min, sec) } pub fn day_diff(&self, other: &DateUtc) -> u32 { @@ -57,7 +61,8 @@ impl DateUtc { } pub fn days_in_month(&self) -> u32 { - self.first_day_in_next_month().day_diff(&self.first_day_in_month()) + self.first_day_in_next_month() + .day_diff(&self.first_day_in_month()) } pub fn add_days(&self, days: u64) -> Result<Self> { @@ -66,7 +71,9 @@ impl DateUtc { .checked_add_days(chrono::Days::new(days)) .with_context(|| format!("failed to add {} days to {}", days, self)) .unwrap(); - Ok(Self { chrono_datetime_utc }) + Ok(Self { + chrono_datetime_utc, + }) } pub fn sub_days(&self, days: u64) -> Result<Self> { @@ -75,7 +82,9 @@ impl DateUtc { .checked_sub_days(chrono::Days::new(days)) .with_context(|| format!("failed to subtract {} days from {}", days, self)) .unwrap(); - Ok(Self { chrono_datetime_utc }) + Ok(Self { + chrono_datetime_utc, + }) } fn is_day_str(str: &str) -> bool { @@ -101,10 +110,14 @@ impl DateUtc { let mut curr_guess: Option<DateTime<Utc>> = None; let mut curr_add = 1; while curr_guess.is_none() || curr_guess.unwrap().month() == month { - curr_guess = self.chrono_datetime_utc.checked_add_days(chrono::Days::new(curr_add)); + curr_guess = self + .chrono_datetime_utc + .checked_add_days(chrono::Days::new(curr_add)); curr_add = curr_add + 1; + } + return Self { + chrono_datetime_utc: curr_guess.unwrap(), }; - return Self { chrono_datetime_utc: curr_guess.unwrap() }; } fn first_day_in_month(&self) -> Self { @@ -120,7 +133,9 @@ impl DateUtc { if curr_subtractor > 31 { return prev_guess; } - next = self.chrono_datetime_utc.checked_sub_days(chrono::Days::new(curr_subtractor)); + next = self + .chrono_datetime_utc + .checked_sub_days(chrono::Days::new(curr_subtractor)); curr_subtractor = curr_subtractor + 1; } let next = next.unwrap(); @@ -128,7 +143,7 @@ impl DateUtc { curr_guess = Self { chrono_datetime_utc: next, }; - }; + } return prev_guess; } } @@ -136,11 +151,7 @@ impl DateUtc { impl Nowlike for DateUtc { fn now() -> Self { let now = Utc::now(); - Self::from_ymd( - now.year(), - now.month(), - now.day(), - ).unwrap() + Self::from_ymd(now.year(), now.month(), now.day()).unwrap() } } @@ -169,18 +180,24 @@ impl From<&DatetimeUtc> for DateUtc { Self { chrono_datetime_utc: datetime_utc .to_string() - .parse::<DateTime<Utc>>().unwrap() - .with_time(NaiveTime::from_hms_opt(0, 0, 0).unwrap()).unwrap(), + .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>> { +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(), + .with_time(NaiveTime::from_hms_opt(0, 0, 0).unwrap()) + .unwrap(), } } } @@ -190,10 +207,7 @@ impl fmt::Display for DateUtc { /// 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; + let day_str = date_str.split_at_checked(10).unwrap().0; write!(f, "{}", day_str) } } @@ -205,7 +219,10 @@ impl FromStr for DateUtc { /// 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))) + 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"); @@ -235,7 +252,7 @@ impl FromSql<Text, Sqlite> for DateUtc { #[cfg(test)] mod test { - use schist_traits::timeable::Timeable; + use schist_traits::Timeable; use super::*; @@ -267,15 +284,30 @@ mod test { 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_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_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_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_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"); + assert_eq!( + date_utc_5.unwrap_err().to_string(), + "failed to construct date from ymd 1971-02-29" + ); } #[test] @@ -314,7 +346,9 @@ mod test { #[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); + 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(); @@ -339,8 +373,14 @@ mod test { #[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 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); @@ -498,50 +538,74 @@ mod test { } fn get_dates_in_jan_2024() -> Vec<DateUtc> { - (1..31).map(|day| format!("2024-01-{:02}", day).parse::<DateUtc>().unwrap()).collect::<Vec<DateUtc>>() + (1..31) + .map(|day| format!("2024-01-{:02}", day).parse::<DateUtc>().unwrap()) + .collect::<Vec<DateUtc>>() } fn get_dates_in_feb_2024() -> Vec<DateUtc> { - (1..29).map(|day| format!("2024-02-{:02}", day).parse::<DateUtc>().unwrap()).collect::<Vec<DateUtc>>() + (1..29) + .map(|day| format!("2024-02-{:02}", day).parse::<DateUtc>().unwrap()) + .collect::<Vec<DateUtc>>() } fn get_dates_in_mar_2024() -> Vec<DateUtc> { - (1..31).map(|day| format!("2024-03-{:02}", day).parse::<DateUtc>().unwrap()).collect::<Vec<DateUtc>>() + (1..31) + .map(|day| format!("2024-03-{:02}", day).parse::<DateUtc>().unwrap()) + .collect::<Vec<DateUtc>>() } fn get_dates_in_apr_2024() -> Vec<DateUtc> { - (1..30).map(|day| format!("2024-04-{:02}", day).parse::<DateUtc>().unwrap()).collect::<Vec<DateUtc>>() + (1..30) + .map(|day| format!("2024-04-{:02}", day).parse::<DateUtc>().unwrap()) + .collect::<Vec<DateUtc>>() } fn get_dates_in_may_2024() -> Vec<DateUtc> { - (1..31).map(|day| format!("2024-05-{:02}", day).parse::<DateUtc>().unwrap()).collect::<Vec<DateUtc>>() + (1..31) + .map(|day| format!("2024-05-{:02}", day).parse::<DateUtc>().unwrap()) + .collect::<Vec<DateUtc>>() } fn get_dates_in_jun_2024() -> Vec<DateUtc> { - (1..30).map(|day| format!("2024-06-{:02}", day).parse::<DateUtc>().unwrap()).collect::<Vec<DateUtc>>() + (1..30) + .map(|day| format!("2024-06-{:02}", day).parse::<DateUtc>().unwrap()) + .collect::<Vec<DateUtc>>() } fn get_dates_in_jul_2024() -> Vec<DateUtc> { - (1..31).map(|day| format!("2024-07-{:02}", day).parse::<DateUtc>().unwrap()).collect::<Vec<DateUtc>>() + (1..31) + .map(|day| format!("2024-07-{:02}", day).parse::<DateUtc>().unwrap()) + .collect::<Vec<DateUtc>>() } fn get_dates_in_aug_2024() -> Vec<DateUtc> { - (1..31).map(|day| format!("2024-08-{:02}", day).parse::<DateUtc>().unwrap()).collect::<Vec<DateUtc>>() + (1..31) + .map(|day| format!("2024-08-{:02}", day).parse::<DateUtc>().unwrap()) + .collect::<Vec<DateUtc>>() } fn get_dates_in_sep_2024() -> Vec<DateUtc> { - (1..30).map(|day| format!("2024-09-{:02}", day).parse::<DateUtc>().unwrap()).collect::<Vec<DateUtc>>() + (1..30) + .map(|day| format!("2024-09-{:02}", day).parse::<DateUtc>().unwrap()) + .collect::<Vec<DateUtc>>() } fn get_dates_in_oct_2024() -> Vec<DateUtc> { - (1..31).map(|day| format!("2024-10-{:02}", day).parse::<DateUtc>().unwrap()).collect::<Vec<DateUtc>>() + (1..31) + .map(|day| format!("2024-10-{:02}", day).parse::<DateUtc>().unwrap()) + .collect::<Vec<DateUtc>>() } fn get_dates_in_nov_2024() -> Vec<DateUtc> { - (1..30).map(|day| format!("2024-11-{:02}", day).parse::<DateUtc>().unwrap()).collect::<Vec<DateUtc>>() + (1..30) + .map(|day| format!("2024-11-{:02}", day).parse::<DateUtc>().unwrap()) + .collect::<Vec<DateUtc>>() } fn get_dates_in_dec_2024() -> Vec<DateUtc> { - (1..31).map(|day| format!("2024-12-{:02}", day).parse::<DateUtc>().unwrap()).collect::<Vec<DateUtc>>() + (1..31) + .map(|day| format!("2024-12-{:02}", day).parse::<DateUtc>().unwrap()) + .collect::<Vec<DateUtc>>() } } diff --git a/schist_core/schist_models/src/datetime_utc.rs b/schist_core/schist_models/src/datetime_utc.rs index 9b63145..4f3b165 100644 --- a/schist_core/schist_models/src/datetime_utc.rs +++ b/schist_core/schist_models/src/datetime_utc.rs @@ -12,19 +12,10 @@ use diesel::{ }; use serde::{Deserialize, Serialize}; -use schist_traits::{dateable::Dateable, nowlike::Nowlike, timeable::Timeable}; +use schist_traits::{Dateable, Nowlike, Timeable}; #[derive( - PartialEq, - Eq, - PartialOrd, - Ord, - Serialize, - Deserialize, - Clone, - Debug, - AsExpression, - FromSqlRow, + PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Clone, Debug, AsExpression, FromSqlRow, )] #[diesel(sql_type=Text)] pub struct DatetimeUtc { @@ -32,13 +23,30 @@ pub struct DatetimeUtc { } impl DatetimeUtc { - pub fn from_ymd_and_hms(year: i32, month: u32, day: u32, hour: u32, min: u32, sec: u32) -> Result<Self> { - Ok(Self { chrono_datetime_utc: NaiveDate - ::from_ymd_opt(year, month, day) - .with_context(|| format!("failed to construct datetime from ymd {:04}-{:02}-{:02}", year, month, day))? - .and_hms_opt(hour, min, sec) - .with_context(|| format!("failed to construct datetime from hms {:02}:{:02}:{:02}", hour, min, sec))? - .and_utc() + pub fn from_ymd_and_hms( + year: i32, + month: u32, + day: u32, + hour: u32, + min: u32, + sec: u32, + ) -> Result<Self> { + Ok(Self { + chrono_datetime_utc: NaiveDate::from_ymd_opt(year, month, day) + .with_context(|| { + format!( + "failed to construct datetime from ymd {:04}-{:02}-{:02}", + year, month, day + ) + })? + .and_hms_opt(hour, min, sec) + .with_context(|| { + format!( + "failed to construct datetime from hms {:02}:{:02}:{:02}", + hour, min, sec + ) + })? + .and_utc(), }) } } @@ -60,7 +68,12 @@ impl Display for DatetimeUtc { /// Converts to a date string in ISO format, in UTC /// Example: 10.30am 24 Oct 2024 UTC -> "2024-10-24T10:30:00.000Z" fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "{}", self.chrono_datetime_utc.to_rfc3339_opts(chrono::SecondsFormat::Millis, true)) + write!( + f, + "{}", + self.chrono_datetime_utc + .to_rfc3339_opts(chrono::SecondsFormat::Millis, true) + ) } } @@ -74,7 +87,8 @@ impl Nowlike for DatetimeUtc { now.hour(), now.minute(), now.second(), - ).unwrap() + ) + .unwrap() } } @@ -161,21 +175,45 @@ mod test { let datetime_utc_8 = DatetimeUtc::from_ymd_and_hms(1970, 11, 23, 0, 0, 61); assert!(datetime_utc_1.is_err()); - assert_eq!(datetime_utc_1.unwrap_err().to_string(), "failed to construct datetime from ymd 1970-00-23"); + assert_eq!( + datetime_utc_1.unwrap_err().to_string(), + "failed to construct datetime from ymd 1970-00-23" + ); assert!(datetime_utc_2.is_err()); - assert_eq!(datetime_utc_2.unwrap_err().to_string(), "failed to construct datetime from ymd 1970-13-23"); + assert_eq!( + datetime_utc_2.unwrap_err().to_string(), + "failed to construct datetime from ymd 1970-13-23" + ); assert!(datetime_utc_3.is_err()); - assert_eq!(datetime_utc_3.unwrap_err().to_string(), "failed to construct datetime from ymd 1970-11-00"); + assert_eq!( + datetime_utc_3.unwrap_err().to_string(), + "failed to construct datetime from ymd 1970-11-00" + ); assert!(datetime_utc_4.is_err()); - assert_eq!(datetime_utc_4.unwrap_err().to_string(), "failed to construct datetime from ymd 1970-11-31"); + assert_eq!( + datetime_utc_4.unwrap_err().to_string(), + "failed to construct datetime from ymd 1970-11-31" + ); assert!(datetime_utc_5.is_err()); - assert_eq!(datetime_utc_5.unwrap_err().to_string(), "failed to construct datetime from ymd 1971-02-29"); + assert_eq!( + datetime_utc_5.unwrap_err().to_string(), + "failed to construct datetime from ymd 1971-02-29" + ); assert!(datetime_utc_6.is_err()); - assert_eq!(datetime_utc_6.unwrap_err().to_string(), "failed to construct datetime from hms 25:00:00"); + assert_eq!( + datetime_utc_6.unwrap_err().to_string(), + "failed to construct datetime from hms 25:00:00" + ); assert!(datetime_utc_7.is_err()); - assert_eq!(datetime_utc_7.unwrap_err().to_string(), "failed to construct datetime from hms 00:61:00"); + assert_eq!( + datetime_utc_7.unwrap_err().to_string(), + "failed to construct datetime from hms 00:61:00" + ); assert!(datetime_utc_8.is_err()); - assert_eq!(datetime_utc_8.unwrap_err().to_string(), "failed to construct datetime from hms 00:00:61"); + assert_eq!( + datetime_utc_8.unwrap_err().to_string(), + "failed to construct datetime from hms 00:00:61" + ); } #[test] @@ -197,7 +235,10 @@ mod test { let datetime_utc: Result<DatetimeUtc> = "1970-11-23T12:55:16.000Z".parse(); assert!(datetime_utc.is_ok()); - assert_eq!(datetime_utc.unwrap().to_string(), "1970-11-23T12:55:16.000Z") + assert_eq!( + datetime_utc.unwrap().to_string(), + "1970-11-23T12:55:16.000Z" + ) } #[test] diff --git a/schist_core/schist_models/src/lib.rs b/schist_core/schist_models/src/lib.rs index 503db17..3aa4733 100644 --- a/schist_core/schist_models/src/lib.rs +++ b/schist_core/schist_models/src/lib.rs @@ -1,12 +1,24 @@ -pub mod account; -pub mod account_transfer; -pub mod bucket; -pub mod bucket_transfer; -pub mod budget_period_unit; -pub mod date_utc; -pub mod datetime_utc; -pub mod drip; +mod account; +mod account_transfer; +mod bucket; +mod bucket_transfer; +mod budget_period_unit; +mod date_utc; +mod datetime_utc; +mod drip; +mod pipe; +mod transaction; + pub mod migrations; -pub mod pipe; pub mod schema; -pub mod transaction; + +pub use account::Account; +pub use account_transfer::{AccountTransfer, AccountTransferBuilder}; +pub use bucket::{Bucket, BucketBuilder}; +pub use bucket_transfer::{BucketTransfer, BucketTransferBuilder}; +pub use budget_period_unit::BudgetPeriodUnit; +pub use date_utc::DateUtc; +pub use datetime_utc::DatetimeUtc; +pub use drip::{Drip, DripBuilder}; +pub use pipe::{Pipe, PipeBuilder}; +pub use transaction::{Transaction, TransactionBuilder}; |
