summaryrefslogtreecommitdiff
path: root/rust/schist_models/src
diff options
context:
space:
mode:
authorJoe Carstairs <me@joeac.net>2024-11-24 22:53:10 +0000
committerJoe Carstairs <me@joeac.net>2024-11-24 23:16:05 +0000
commit06770a965f75416c22ef7115004a250388cebcbf (patch)
treef4125385fdd50d2014bd8f7c2a44d7c462b8c3be /rust/schist_models/src
parent366f3e98bafaa8a6d364d62496ab7139935bfdec (diff)
transform budget drips
Diffstat (limited to 'rust/schist_models/src')
-rw-r--r--rust/schist_models/src/budget_drip.rs2
-rw-r--r--rust/schist_models/src/date_utc.rs65
2 files changed, 66 insertions, 1 deletions
diff --git a/rust/schist_models/src/budget_drip.rs b/rust/schist_models/src/budget_drip.rs
index f467ecd..2cc2c63 100644
--- a/rust/schist_models/src/budget_drip.rs
+++ b/rust/schist_models/src/budget_drip.rs
@@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
use crate::date_utc::DateUtc;
-#[derive(Builder, Queryable, Identifiable, Selectable, Debug, PartialEq, Serialize, Deserialize, Insertable)]
+#[derive(Builder, Clone, Copy, Queryable, Identifiable, Selectable, Debug, PartialEq, Serialize, Deserialize, Insertable)]
#[diesel(table_name = crate::schema::budget_drips)]
pub struct BudgetDrip {
pub id: i32,
diff --git a/rust/schist_models/src/date_utc.rs b/rust/schist_models/src/date_utc.rs
index 3f5391c..c801585 100644
--- a/rust/schist_models/src/date_utc.rs
+++ b/rust/schist_models/src/date_utc.rs
@@ -24,6 +24,7 @@ use crate::datetime_utc::DatetimeUtc;
Serialize,
Deserialize,
Clone,
+ Copy,
Debug,
AsExpression,
FromSqlRow,
@@ -55,6 +56,19 @@ impl DateUtc {
.abs_diff(other.chrono_datetime_utc.num_days_from_ce())
}
+ pub fn days_in_month(&self) -> u32 {
+ self.first_day_in_next_month().day_diff(&self.first_day_in_month())
+ }
+
+ pub fn add_days(&self, days: u64) -> Result<Self> {
+ let chrono_datetime_utc = self
+ .chrono_datetime_utc
+ .checked_add_days(chrono::Days::new(days))
+ .with_context(|| format!("failed to add {} days to {}", days, self))
+ .unwrap();
+ Ok(Self { chrono_datetime_utc })
+ }
+
fn is_day_str(str: &str) -> bool {
if str.len() != 10 {
return false;
@@ -72,6 +86,42 @@ impl DateUtc {
}
return true;
}
+
+ fn first_day_in_next_month(&self) -> Self {
+ let month = self.month();
+ 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_add = curr_add + 1;
+ };
+ return Self { chrono_datetime_utc: curr_guess.unwrap() };
+ }
+
+ fn first_day_in_month(&self) -> Self {
+ let month = self.month();
+ let mut prev_guess = self.clone();
+ let mut curr_guess = self.clone();
+ let mut curr_subtractor = 1;
+ while curr_guess.month() == month {
+ prev_guess = curr_guess.clone();
+
+ let mut next: Option<DateTime<Utc>> = None;
+ while next.is_none() {
+ if curr_subtractor > 31 {
+ return prev_guess;
+ }
+ next = self.chrono_datetime_utc.checked_sub_days(chrono::Days::new(curr_subtractor));
+ curr_subtractor = curr_subtractor + 1;
+ }
+ let next = next.unwrap();
+
+ curr_guess = Self {
+ chrono_datetime_utc: next,
+ };
+ };
+ return prev_guess;
+ }
}
impl Nowlike for DateUtc {
@@ -306,4 +356,19 @@ mod test {
assert_eq!(day_diff, 1);
assert_eq!(day_diff, neg_day_diff);
}
+
+ #[test]
+ fn test_first_day_in_month() {
+ todo!();
+ }
+
+ #[test]
+ fn test_first_day_in_next_month() {
+ todo!();
+ }
+
+ #[test]
+ fn test_days_in_month() {
+ todo!();
+ }
}