use chrono::{DateTime, Local, Datelike, Timelike, TimeZone};
use serde::{Serialize, Deserialize};
use pelican_ui::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 direct(&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 friendly(&self) -> Option<String> {
let dt = self.to_datetime()?;
let today = Local::now().date_naive();
let date = dt.date_naive();
match date == today {
true => {
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")
};
format!("{hour12}:{minute:02} {am_pm}").into()
},
false if date == today.pred_opt().unwrap_or(today) => "Yesterday".to_string().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)>;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ElementID(uuid::Uuid);
impl ElementID {
pub fn new() -> Self {
ElementID(uuid::Uuid::new_v4())
}
pub fn as_uuid(&self) -> uuid::Uuid {
self.0
}
}
impl Default for ElementID {
fn default() -> Self {
Self::new()
}
}