mps-rs 1.1.0

MPS — plain-text personal productivity CLI (Rust)
Documentation
use super::split_args;

#[derive(Debug, Clone)]
pub struct LogData {
    pub tags:  Vec<String>,
    pub start: Option<String>,  // "HH:MM"
    pub end:   Option<String>,  // "HH:MM"
}

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(),
        }
    }

    /// Duration in minutes, or None if start/end are not both present.
    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))
    }

    /// "3h30m" or "3h" or None.
    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));
    }
}