102 lines
2.4 KiB
Rust
102 lines
2.4 KiB
Rust
use std::collections::HashSet;
|
|
|
|
use anyhow::{anyhow, bail};
|
|
|
|
pub struct Date {
|
|
pub day: u8,
|
|
pub month: u8,
|
|
pub year: u16,
|
|
}
|
|
|
|
impl Date {
|
|
/// Create a day from String. Expects strings in format '06-26-2026'
|
|
pub fn from_string(val: &str) -> anyhow::Result<Self> {
|
|
let mut parts = val.split("-");
|
|
let month = parts
|
|
.next()
|
|
.ok_or(anyhow!("Month missing from date string"))?
|
|
.parse()?;
|
|
|
|
if month > 12 || month == 0 {
|
|
bail!("Month should be > 0 and <= 12")
|
|
}
|
|
|
|
let day = parts
|
|
.next()
|
|
.ok_or(anyhow!("Day missing from date string"))?
|
|
.parse()?;
|
|
|
|
if day == 0 {
|
|
bail!("Day must be > 0")
|
|
}
|
|
|
|
match month {
|
|
2 => {
|
|
if day > 29 {
|
|
bail!("February can have a max of 29 days (on leap years)")
|
|
}
|
|
}
|
|
4 | 6 | 9 | 11 => {
|
|
if day > 30 {
|
|
bail!("The provided month only has 30 days")
|
|
}
|
|
}
|
|
1 | 3 | 5 | 7 | 8 | 10 | 12 => {
|
|
if day > 31 {
|
|
bail!("The provided month only has 31 days")
|
|
}
|
|
}
|
|
_ => unreachable!(),
|
|
}
|
|
|
|
let year = parts
|
|
.next()
|
|
.ok_or(anyhow!("Year missing from date string"))?
|
|
.parse()?;
|
|
|
|
Ok(Date { day, month, year })
|
|
}
|
|
}
|
|
|
|
pub struct Habit {
|
|
pub name: String,
|
|
pub days_completed: HashSet<Date>,
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
use crate::model::Date;
|
|
|
|
#[test]
|
|
fn correct_date_gets_parsed() {
|
|
let date = Date::from_string("06-16-2026").unwrap();
|
|
|
|
assert_eq!(date.day, 16);
|
|
assert_eq!(date.month, 6);
|
|
assert_eq!(date.year, 2026);
|
|
|
|
let date = Date::from_string("6-16-2026").unwrap();
|
|
|
|
assert_eq!(date.day, 16);
|
|
assert_eq!(date.month, 6);
|
|
assert_eq!(date.year, 2026);
|
|
|
|
let date = Date::from_string("6-6-2026").unwrap();
|
|
|
|
assert_eq!(date.day, 6);
|
|
assert_eq!(date.month, 6);
|
|
assert_eq!(date.year, 2026);
|
|
}
|
|
|
|
#[test]
|
|
fn bad_date_doesnt_get_parsed() {
|
|
let date = Date::from_string("-12-2026");
|
|
assert!(date.is_err());
|
|
|
|
let date = Date::from_string("13-01-2026");
|
|
assert!(date.is_err());
|
|
|
|
let date = Date::from_string("01-32-2026");
|
|
assert!(date.is_err());
|
|
}
|
|
}
|