diff options
author | Benedikt Peetz <benedikt.peetz@b-peetz.de> | 2025-02-14 16:44:53 +0100 |
---|---|---|
committer | Benedikt Peetz <benedikt.peetz@b-peetz.de> | 2025-02-14 16:44:53 +0100 |
commit | 14db4eadd57d0a3837227d9d74b84a133bacd434 (patch) | |
tree | 6a269bb25cf7204cfbdf776a12eeb3490a1ed6cd | |
parent | fix(yt/download/download_options): Stop trying to write annotations (diff) | |
download | yt-14db4eadd57d0a3837227d9d74b84a133bacd434.zip |
feat(yt/select/selection_file/duration): Support durations up to days
The current maximum of hours was enough in most cases, but not for all cases.
-rw-r--r-- | yt/src/select/selection_file/duration.rs | 61 |
1 files changed, 43 insertions, 18 deletions
diff --git a/yt/src/select/selection_file/duration.rs b/yt/src/select/selection_file/duration.rs index ab3a18b..2953bd3 100644 --- a/yt/src/select/selection_file/duration.rs +++ b/yt/src/select/selection_file/duration.rs @@ -14,19 +14,36 @@ use anyhow::{Context, Result}; use crate::unreachable::Unreachable; +const SECOND: u64 = 1; +const MINUTE: u64 = 60 * SECOND; +const HOUR: u64 = 60 * MINUTE; +const DAY: u64 = 24 * HOUR; + #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct Duration { - time: u32, + time: u64, +} + +impl Duration { + #[must_use] + pub fn from_std(d: std::time::Duration) -> Self { + Self { time: d.as_secs() } + } + + #[must_use] + pub fn value(&self) -> u64 { + self.time + } } impl FromStr for Duration { type Err = anyhow::Error; fn from_str(s: &str) -> Result<Self, Self::Err> { - fn parse_num(str: &str, suffix: char) -> Result<u32> { + fn parse_num(str: &str, suffix: char) -> Result<u64> { str.strip_suffix(suffix) .with_context(|| format!("Failed to strip suffix '{suffix}' of number: '{str}'"))? - .parse::<u32>() + .parse::<u64>() .with_context(|| format!("Failed to parse '{suffix}'")) } @@ -36,17 +53,25 @@ impl FromStr for Duration { let buf: Vec<_> = s.split(' ').collect(); + let days; let hours; let minutes; let seconds; assert_eq!(buf.len(), 2, "Other lengths should not happen"); - if buf[0].ends_with('h') { + if buf[0].ends_with('d') { + days = parse_num(buf[0], 'd')?; + hours = parse_num(buf[1], 'h')?; + minutes = parse_num(buf[2], 'm')?; + seconds = 0; + } else if buf[0].ends_with('h') { + days = 0; hours = parse_num(buf[0], 'h')?; minutes = parse_num(buf[1], 'm')?; seconds = 0; } else if buf[0].ends_with('m') { + days = 0; hours = 0; minutes = parse_num(buf[0], 'm')?; seconds = parse_num(buf[1], 's')?; @@ -58,7 +83,7 @@ impl FromStr for Duration { } Ok(Self { - time: (hours * 60 * 60) + (minutes * 60) + seconds, + time: days * DAY + hours * HOUR + minutes * MINUTE + seconds * SECOND, }) } } @@ -67,32 +92,32 @@ impl From<Option<f64>> for Duration { fn from(value: Option<f64>) -> Self { Self { #[allow(clippy::cast_possible_truncation)] - time: u32::try_from(value.unwrap_or(0.0).ceil() as i128) - .unreachable("This should not exceed `u32::MAX`"), + time: u64::try_from(value.unwrap_or(0.0).ceil() as i128) + .unreachable("This should not exceed `u64::MAX`"), } } } impl std::fmt::Display for Duration { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { - const SECOND: u32 = 1; - const MINUTE: u32 = 60 * SECOND; - const HOUR: u32 = 60 * MINUTE; - - let base_hour = self.time - (self.time % HOUR); - let base_min = (self.time % HOUR) - ((self.time % HOUR) % MINUTE); - let base_sec = (self.time % HOUR) % MINUTE; + fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { + let base_day = self.time - (self.time % DAY); + let base_hour = (self.time % DAY) - ((self.time % DAY) % HOUR); + let base_min = (self.time % HOUR) - (((self.time % DAY) % HOUR) % MINUTE); + let base_sec = ((self.time % DAY) % HOUR) % MINUTE; + let d = base_day / DAY; let h = base_hour / HOUR; let m = base_min / MINUTE; let s = base_sec / SECOND; if self.time == 0 { - write!(f, "[No duration]") + write!(fmt, "[No duration]") + } else if d > 0 { + write!(fmt, "{d}d {h}h {m}m") } else if h > 0 { - write!(f, "{h}h {m}m") + write!(fmt, "{h}h {m}m") } else { - write!(f, "{m}m {s}s") + write!(fmt, "{m}m {s}s") } } } |