// yt - A fully featured command line YouTube client // // Copyright (C) 2024 Benedikt Peetz <benedikt.peetz@b-peetz.de> // SPDX-License-Identifier: GPL-3.0-or-later // // This file is part of Yt. // // You should have received a copy of the License along with this program. // If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>. // TODO: This file should be de-duplicated with the same file in the 'yt' crate <2024-06-25> pub struct Duration { time: u32, } impl From<&str> for Duration { fn from(v: &str) -> Self { let buf: Vec<_> = v.split(':').take(2).collect(); Self { time: (buf[0].parse::<u32>().expect("Should be a number") * 60) + buf[1].parse::<u32>().expect("Should be a number"), } } } impl From<Option<f64>> for Duration { fn from(value: Option<f64>) -> Self { Self { time: value.unwrap_or(0.0).ceil() as u32, } } } 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; let h = base_hour / HOUR; let m = base_min / MINUTE; let s = base_sec / SECOND; if self.time == 0 { write!(f, "0s") } else if h > 0 { write!(f, "{h}h {m}m") } else { write!(f, "{m}m {s}s") } } } #[cfg(test)] mod test { use super::Duration; #[test] fn test_display_duration_1h() { let dur = Duration { time: 60 * 60 }; assert_eq!("[1h 0m]".to_owned(), dur.to_string()); } #[test] fn test_display_duration_30min() { let dur = Duration { time: 60 * 30 }; assert_eq!("[30m 0s]".to_owned(), dur.to_string()); } }