use crate::{convert::convert_to_naive_date, convert_date_to_timestamp, parse_date, Error, Result};
use chrono::NaiveDate;
use std::{fmt, str::FromStr};
#[derive(Clone, Debug, Default, PartialEq)]
pub struct MealRecord {
meal: String,
timestamp: i64,
}
impl MealRecord {
pub fn new(meal: &str, date: &str) -> Result<Self> {
let mut dates = parse_date(date)?;
if dates.len() > 1 {
return Err(Error::MoreThanOneDate(date.to_string()));
}
let naive_date = dates.pop().unwrap();
let timestamp = convert_date_to_timestamp(&naive_date);
Ok(MealRecord {
meal: meal.to_string(),
timestamp,
})
}
pub fn from_meal_and_naivedate(meal: &str, naive_date: &NaiveDate) -> Self {
let timestamp = convert_date_to_timestamp(naive_date);
MealRecord {
meal: meal.to_string(),
timestamp,
}
}
pub fn from_meal_and_timestamp(meal: &str, timestamp: i64) -> Result<Self> {
let naive_date = convert_to_naive_date(timestamp)?;
let timestamp = convert_date_to_timestamp(&naive_date);
Ok(MealRecord {
meal: meal.to_string(),
timestamp,
})
}
pub fn meal(&self) -> String {
self.meal.clone()
}
pub fn naive_date(&self) -> NaiveDate {
convert_to_naive_date(self.timestamp)
.expect("this MealRecord somehow bypassed the timestamp validity check")
}
pub fn timestamp(&self) -> i64 {
self.timestamp
}
}
impl FromStr for MealRecord {
type Err = Error;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
let mut split = s.split(", ");
let timestamp = split
.next()
.ok_or(Error::ParseMealRecordError)?
.parse::<i64>()?;
let meal = String::from(split.next().ok_or(Error::ParseMealRecordError)?);
Ok(MealRecord { meal, timestamp })
}
}
impl fmt::Display for MealRecord {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{} ({})", self.meal(), self.naive_date())
}
}