Skip to main content

systemprompt_cli/commands/infrastructure/logs/
duration.rs

1//! Duration parsing for log-command time filters.
2//!
3//! Copyright (c) systemprompt.io — Business Source License 1.1.
4//! See <https://systemprompt.io> for licensing details.
5
6use anyhow::{Result, anyhow};
7use chrono::{DateTime, Duration, Utc};
8
9pub fn parse_duration(s: &str) -> Result<Duration> {
10    let s = s.trim().to_lowercase();
11
12    if let Some(days) = s.strip_suffix('d') {
13        let num: i64 = days
14            .parse()
15            .map_err(|_e| anyhow!("Invalid duration: {}", s))?;
16        return Ok(Duration::days(num));
17    }
18
19    if let Some(hours) = s.strip_suffix('h') {
20        let num: i64 = hours
21            .parse()
22            .map_err(|_e| anyhow!("Invalid duration: {}", s))?;
23        return Ok(Duration::hours(num));
24    }
25
26    if let Some(mins) = s.strip_suffix('m') {
27        let num: i64 = mins
28            .parse()
29            .map_err(|_e| anyhow!("Invalid duration: {}", s))?;
30        return Ok(Duration::minutes(num));
31    }
32
33    if let Ok(num) = s.parse::<i64>() {
34        return Ok(Duration::days(num));
35    }
36
37    Err(anyhow!(
38        "Invalid duration format: {}. Use formats like '7d', '24h', '30m'",
39        s
40    ))
41}
42
43pub fn parse_since(since: Option<&String>) -> Result<Option<DateTime<Utc>>> {
44    let Some(s) = since else {
45        return Ok(None);
46    };
47
48    let s = s.trim().to_lowercase();
49
50    if let Ok(duration) = parse_duration(&s) {
51        return Ok(Some(Utc::now() - duration));
52    }
53
54    if let Ok(date) = chrono::NaiveDate::parse_from_str(&s, "%Y-%m-%d") {
55        let datetime = date
56            .and_hms_opt(0, 0, 0)
57            .ok_or_else(|| anyhow!("Invalid date: {}", s))?;
58        return Ok(Some(DateTime::from_naive_utc_and_offset(datetime, Utc)));
59    }
60
61    if let Ok(dt) = DateTime::parse_from_str(&format!("{}+00:00", s), "%Y-%m-%dT%H:%M:%S%:z") {
62        return Ok(Some(dt.with_timezone(&Utc)));
63    }
64
65    Err(anyhow!(
66        "Invalid --since format: {}. Use formats like '1h', '24h', '7d', '2026-01-13', or \
67         '2026-01-13T10:00:00'",
68        s
69    ))
70}