use super::split_args;
#[derive(Debug, Clone)]
pub struct LogData {
pub tags: Vec<String>,
pub start: Option<String>, pub end: Option<String>, }
impl LogData {
pub fn parse_args(raw: &str) -> Self {
let p = split_args(raw);
LogData {
tags: p.tags,
start: p.attrs.get("start").cloned(),
end: p.attrs.get("end").cloned(),
}
}
pub fn duration_minutes(&self) -> Option<i64> {
let s = self.start.as_deref()?;
let e = self.end.as_deref()?;
let (sh, sm) = parse_hhmm(s)?;
let (eh, em) = parse_hhmm(e)?;
Some((eh * 60 + em) - (sh * 60 + sm))
}
pub fn duration_str(&self) -> Option<String> {
let mins = self.duration_minutes()?;
if mins <= 0 {
return None;
}
let h = mins / 60;
let m = mins % 60;
if m > 0 {
Some(format!("{}h{}m", h, m))
} else {
Some(format!("{}h", h))
}
}
}
fn parse_hhmm(s: &str) -> Option<(i64, i64)> {
let mut parts = s.splitn(2, ':');
let h: i64 = parts.next()?.trim().parse().ok()?;
let m: i64 = parts.next()?.trim().parse().ok()?;
Some((h, m))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_duration_str() {
let d = LogData::parse_args("work, start: 09:00, end: 12:30");
assert_eq!(d.duration_str(), Some("3h30m".into()));
}
#[test]
fn test_exact_hours() {
let d = LogData::parse_args("start: 09:00, end: 12:00");
assert_eq!(d.duration_str(), Some("3h".into()));
}
#[test]
fn test_no_times() {
let d = LogData::parse_args("work");
assert_eq!(d.duration_str(), None);
}
#[test]
fn test_duration_minutes() {
let d = LogData::parse_args("start: 09:00, end: 12:30");
assert_eq!(d.duration_minutes(), Some(210));
}
}