kasl/libs/pause.rs
1//! The pause model shared by the monitor, the database layer and the views.
2//!
3//! ```rust,no_run
4//! # fn f() -> Result<(), chrono::ParseError> {
5//! use kasl::libs::pause::Pause;
6//! use chrono::{NaiveDateTime, Duration};
7//!
8//! let pause = Pause::detected(
9//! 1,
10//! NaiveDateTime::parse_from_str("2025-08-11 09:15:00", "%Y-%m-%d %H:%M:%S")?,
11//! Some(NaiveDateTime::parse_from_str("2025-08-11 09:30:00", "%Y-%m-%d %H:%M:%S")?),
12//! Some(Duration::minutes(15)),
13//! );
14//! # Ok(())
15//! # }
16//! ```
17
18use chrono::{Duration, prelude::NaiveDateTime};
19
20/// A single break period; `end` and `duration` stay `None` while it is ongoing.
21#[derive(Debug, Clone)]
22pub struct Pause {
23 /// Database primary key.
24 pub id: i32,
25
26 /// When the inactivity threshold was crossed (local time).
27 pub start: NaiveDateTime,
28
29 /// When activity resumed; `None` while the pause is still running.
30 pub end: Option<NaiveDateTime>,
31
32 /// `end - start`, stored by the database layer; `None` while ongoing.
33 pub duration: Option<Duration>,
34
35 /// Whether this pause was entered manually and must be preserved as-is.
36 ///
37 /// Protected pauses are recorded by the user through `kasl pauses add`
38 /// rather than detected by the activity monitor. They are exempt from the
39 /// minimum-duration threshold and are never merged with adjacent pauses,
40 /// so a deliberately short entry (a ten-minute walk the monitor missed)
41 /// survives filtering intact.
42 pub protected: bool,
43}
44
45impl Pause {
46 /// Builds a monitor-detected pause (not protected).
47 ///
48 /// Used when reconstructing pauses from sources that carry no protection
49 /// flag, such as in-memory analysis of activity data.
50 pub fn detected(id: i32, start: NaiveDateTime, end: Option<NaiveDateTime>, duration: Option<Duration>) -> Self {
51 Self {
52 id,
53 start,
54 end,
55 duration,
56 protected: false,
57 }
58 }
59}