use chrono::{DateTime, Local, Datelike, Timelike, TimeZone};
use serde::{Serialize, Deserialize};
use roost::Context;
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)]
pub struct Timestamp(String, String);
impl Timestamp {
pub fn new(dt: DateTime<Local>) -> Self {
Timestamp(
dt.format("%-m/%-d/%y").to_string(),
dt.format("%-I:%M %p").to_string()
)
}
pub fn pending() -> Self {
Timestamp("-".to_string(), "-".to_string())
}
pub fn to_datetime(&self) -> Option<DateTime<Local>> {
let combined = format!("{} {}", self.date(), self.time());
let format = "%m/%d/%y %I:%M %p";
let naive = chrono::NaiveDateTime::parse_from_str(&combined, format).expect("Could not parse time");
Local.from_local_datetime(&naive).single()
}
pub fn friendly(&self) -> Option<String> {
let dt = self.to_datetime()?;
let today = Local::now().date_naive();
let date = dt.date_naive();
let hour = dt.hour();
let minute = dt.minute();
let (hour12, am_pm) = match hour == 0 {
true => (12, "am"),
false if hour < 12 => (hour, "am"),
false if hour == 12 => (12, "pm"),
false => (hour - 12, "pm")
};
let the_time = format!("{hour12}:{minute:02} {am_pm}");
match date == today {
true => the_time.into(),
false if date == today.pred_opt().unwrap_or(today) => format!("yesterday, {the_time}").into(),
false if date.iso_week() == today.iso_week() => format!("{}", dt.format("%A")).into(),
false if date.year() == today.year() => format!("{}", dt.format("%B %-d")).into(),
false => format!("{}", dt.format("%m/%d/%y")).into()
}
}
pub fn date(&self) -> String {self.0.clone()}
pub fn time(&self) -> String {self.1.clone()}
}
pub type Callback = Box<dyn FnMut(&mut Context)>;
pub struct TitleSubtitle {
pub title: String,
pub subtitle: String
}
impl TitleSubtitle {
pub fn new(title: &str, subtitle: &str) -> Self {
TitleSubtitle{
title: title.to_string(),
subtitle: subtitle.to_string()
}
}
}