Skip to main content

mps/elements/
log_elem.rs

1use super::split_args;
2
3#[derive(Debug, Clone)]
4pub struct LogData {
5    pub tags:  Vec<String>,
6    pub start: Option<String>,  // "HH:MM"
7    pub end:   Option<String>,  // "HH:MM"
8}
9
10impl LogData {
11    pub fn parse_args(raw: &str) -> Self {
12        let p = split_args(raw);
13        LogData {
14            tags:  p.tags,
15            start: p.attrs.get("start").cloned(),
16            end:   p.attrs.get("end").cloned(),
17        }
18    }
19
20    /// Duration in minutes, or None if start/end are not both present.
21    pub fn duration_minutes(&self) -> Option<i64> {
22        let s = self.start.as_deref()?;
23        let e = self.end.as_deref()?;
24        let (sh, sm) = parse_hhmm(s)?;
25        let (eh, em) = parse_hhmm(e)?;
26        Some((eh * 60 + em) - (sh * 60 + sm))
27    }
28
29    /// "3h30m" or "3h" or None.
30    pub fn duration_str(&self) -> Option<String> {
31        let mins = self.duration_minutes()?;
32        if mins <= 0 { return None; }
33        let h = mins / 60;
34        let m = mins % 60;
35        if m > 0 {
36            Some(format!("{}h{}m", h, m))
37        } else {
38            Some(format!("{}h", h))
39        }
40    }
41}
42
43fn parse_hhmm(s: &str) -> Option<(i64, i64)> {
44    let mut parts = s.splitn(2, ':');
45    let h: i64 = parts.next()?.trim().parse().ok()?;
46    let m: i64 = parts.next()?.trim().parse().ok()?;
47    Some((h, m))
48}
49
50#[cfg(test)]
51mod tests {
52    use super::*;
53
54    #[test]
55    fn test_duration_str() {
56        let d = LogData::parse_args("work, start: 09:00, end: 12:30");
57        assert_eq!(d.duration_str(), Some("3h30m".into()));
58    }
59
60    #[test]
61    fn test_exact_hours() {
62        let d = LogData::parse_args("start: 09:00, end: 12:00");
63        assert_eq!(d.duration_str(), Some("3h".into()));
64    }
65
66    #[test]
67    fn test_no_times() {
68        let d = LogData::parse_args("work");
69        assert_eq!(d.duration_str(), None);
70    }
71
72    #[test]
73    fn test_duration_minutes() {
74        let d = LogData::parse_args("start: 09:00, end: 12:30");
75        assert_eq!(d.duration_minutes(), Some(210));
76    }
77}