diff --git a/Cargo.lock b/Cargo.lock index 4adae16..b9907ef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + [[package]] name = "android-tzdata" version = "0.1.1" @@ -236,6 +245,12 @@ version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + [[package]] name = "num-traits" version = "0.2.17" @@ -269,6 +284,35 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "regex" +version = "1.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" + [[package]] name = "ryu" version = "1.0.15" @@ -331,6 +375,7 @@ version = "0.1.0" dependencies = [ "chrono", "clap", + "regex", "serde", "serde_yaml", ] diff --git a/Cargo.toml b/Cargo.toml index f35f8ba..096f691 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,5 +8,6 @@ edition = "2021" [dependencies] chrono = "0.4.31" clap = { version = "4.4.8", features = ["derive"] } +regex = "1.10.4" serde = { version = "1.0.193", features = ["derive"] } serde_yaml = "0.9.27" diff --git a/src/main.rs b/src/main.rs index 357baa9..7f3d64e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,6 +5,8 @@ use std::time::{SystemTime, UNIX_EPOCH, Duration}; use std::ops::{Add, Sub}; use clap::Parser; use chrono::{TimeZone, Local, Timelike}; +use regex::Regex; +use serde_yaml::from_str; #[derive(Debug, Parser)] struct Flags { @@ -26,6 +28,9 @@ struct Flags { #[arg(short = 'c', long = "clock")] clock: bool, + #[arg(short = 'd', long = "duration")] + duration: Option, + #[arg(short = 'v', long = "verbose")] verbose: bool, @@ -154,6 +159,63 @@ fn log(f: &String, enabled: &bool, since: &Option, verbose: &bool, preci Ok(()) } +#[cfg(test)] +mod test_parse { + use super::*; + + #[test] + fn test_duration() { + assert_eq!(0, parse_duration(&None).unwrap()); + assert_eq!(1, parse_duration(&Some("1s".to_string())).unwrap()); + assert_eq!(33, parse_duration(&Some("33s".to_string())).unwrap()); + assert_eq!(666, parse_duration(&Some("666s".to_string())).unwrap()); + assert_eq!(60, parse_duration(&Some("1m".to_string())).unwrap()); + assert_eq!(62, parse_duration(&Some("1m2s".to_string())).unwrap()); + assert_eq!(3600, parse_duration(&Some("1h".to_string())).unwrap()); + assert_eq!(3723, parse_duration(&Some("1h2m3s".to_string())).unwrap()); + } +} + +fn parse_duration(d: &Option) -> Result { + match d { + Some(d) => { + let mut sum: u64 = 0; + let re = Regex::new(r"^(?[0-9]+h)?(?[0-9]+m)?(?[0-9]+s)?$").unwrap(); + match re.captures(d) { + Some(captures) => { + match captures.name("seconds") { + Some(n) => { + let n = n.as_str().to_string(); + let n = n.trim_end_matches('s'); + sum += from_str::(n).unwrap(); + }, + None => {}, + }; + match captures.name("minutes") { + Some(n) => { + let n = n.as_str().to_string(); + let n = n.trim_end_matches('m'); + sum += 60 * from_str::(n).unwrap(); + }, + None => {}, + }; + match captures.name("hours") { + Some(n) => { + let n = n.as_str().to_string(); + let n = n.trim_end_matches('h'); + sum += 60 * 60 * from_str::(n).unwrap(); + }, + None => {}, + }; + Ok(sum) + }, + None => Ok(0), + } + }, + None => Ok(0), + } +} + fn parse_time(since: &Option) -> Result { match since { Some(since) => {