|
1 | 1 | use clap::Parser; |
2 | 2 | use std::path::PathBuf; |
3 | 3 | use anyhow::{Result, Context}; |
| 4 | +use regex::Regex; |
4 | 5 | use log::info; |
5 | 6 |
|
6 | 7 | mod models; |
@@ -93,54 +94,36 @@ struct Cli { |
93 | 94 | github: bool, |
94 | 95 | } |
95 | 96 |
|
96 | | -// Parse time format strings like "1h", "1h30m", "45min" into seconds |
| 97 | +// Parse time format strings like "1h", "1h30m", "45min", "30s" into seconds |
97 | 98 | fn parse_time_to_seconds(time_str: &str) -> Result<Option<u32>> { |
98 | | - if time_str == "auto" { |
| 99 | + if time_str.eq_ignore_ascii_case("auto") { |
99 | 100 | return Ok(None); |
100 | 101 | } |
101 | | - |
102 | | - let time_str = time_str.to_lowercase(); |
103 | | - let mut total_seconds = 0u32; |
104 | | - |
105 | | - // Handle hours |
106 | | - if let Some(h_pos) = time_str.find('h') { |
107 | | - let hours_str = &time_str[..h_pos]; |
108 | | - if let Ok(hours) = hours_str.parse::<u32>() { |
109 | | - total_seconds += hours * 3600; |
110 | | - } else { |
111 | | - anyhow::bail!("Invalid hour format in: {}", time_str); |
112 | | - } |
113 | | - |
114 | | - // Check for minutes after hours |
115 | | - let remaining = &time_str[h_pos + 1..]; |
116 | | - if !remaining.is_empty() { |
117 | | - // Remove common minute suffixes and parse |
118 | | - let remaining = remaining.replace("min", "").replace('m', ""); |
119 | | - if !remaining.is_empty() { |
120 | | - if let Ok(minutes) = remaining.parse::<u32>() { |
121 | | - if minutes >= 60 { |
122 | | - anyhow::bail!("Minutes cannot be 60 or more: {}", time_str); |
123 | | - } |
124 | | - total_seconds += minutes * 60; |
125 | | - } else { |
126 | | - anyhow::bail!("Invalid minute format in: {}", time_str); |
127 | | - } |
128 | | - } |
129 | | - } |
130 | | - } else { |
131 | | - // Only minutes specified |
132 | | - let minutes_str = time_str.replace("min", "").replace('m', ""); |
133 | | - if let Ok(minutes) = minutes_str.parse::<u32>() { |
134 | | - total_seconds = minutes * 60; |
135 | | - } else { |
136 | | - anyhow::bail!("Invalid time format: {}", time_str); |
| 102 | + |
| 103 | + let re = Regex::new(r"(?i)(\d+)(h|m|min|s)")?; |
| 104 | + let mut total_seconds: u32 = 0; |
| 105 | + let mut matched_any = false; |
| 106 | + |
| 107 | + for cap in re.captures_iter(time_str) { |
| 108 | + matched_any = true; |
| 109 | + let value: u32 = cap[1].parse()?; |
| 110 | + let unit = &cap[2].to_lowercase(); |
| 111 | + |
| 112 | + match unit.as_str() { |
| 113 | + "h" => total_seconds += value * 3600, |
| 114 | + "m" | "min" => total_seconds += value * 60, |
| 115 | + "s" => total_seconds += value, |
| 116 | + _ => anyhow::bail!("Unknown time unit: {}", unit), |
137 | 117 | } |
138 | 118 | } |
139 | | - |
| 119 | + |
| 120 | + if !matched_any { |
| 121 | + anyhow::bail!("Invalid time format: {}", time_str); |
| 122 | + } |
140 | 123 | if total_seconds == 0 { |
141 | 124 | anyhow::bail!("Time cannot be zero: {}", time_str); |
142 | 125 | } |
143 | | - |
| 126 | + |
144 | 127 | Ok(Some(total_seconds)) |
145 | 128 | } |
146 | 129 |
|
|
0 commit comments