#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, Hash)]
pub struct Task {
name: String,
start: chrono::NaiveDateTime,
}
impl Task {
pub fn new<S: ToString + ?Sized>(name: &S) -> Self {
Self { name: name.to_string(), start: chrono::Local::now().naive_local() }
}
#[must_use]
pub fn name(&self) -> &str {
&self.name
}
#[must_use]
pub fn complete(self) -> CompletedTask {
CompletedTask {
name: self.name,
start: self.start,
end: chrono::Local::now().naive_local(),
}
}
}
impl From<&str> for Task {
fn from(name: &str) -> Self {
Self::new(name)
}
}
impl From<String> for Task {
fn from(name: String) -> Self {
Self::new(&name)
}
}
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, Hash)]
pub struct CompletedTask {
pub(crate) name: String,
pub(crate) start: chrono::NaiveDateTime,
pub(crate) end: chrono::NaiveDateTime,
}
impl CompletedTask {
#[must_use]
pub fn name(&self) -> &str {
&self.name
}
#[must_use]
pub fn time(&self) -> chrono::TimeDelta {
self.end - self.start
}
pub fn extend(&mut self, other: &CompletedTask) {
self.end += other.time();
}
#[must_use]
#[allow(clippy::cast_precision_loss)]
pub fn precise_percentage_over(&self, total_time: chrono::TimeDelta) -> f64 {
if let Some(micros) = self.time().num_microseconds()
&& let Some(total_micros) = total_time.num_microseconds()
{
return micros as f64 / total_micros as f64 * 100.0;
}
self.time().num_milliseconds() as f64 / total_time.num_milliseconds() as f64 * 100.0
}
}
impl From<Task> for CompletedTask {
fn from(task: Task) -> Self {
task.complete()
}
}
impl Ord for CompletedTask {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.time().cmp(&other.time())
}
}
impl PartialOrd for CompletedTask {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}