use chrono::Timelike;
use std::fmt;
pub struct MilliTime {
milliday: u32,
}
impl MilliTime {
pub fn from_hms(hour: u32, minute: u32, second: u32) -> Option<Self> {
if hour >= 24 || minute >= 60 || second >= 60 {
return None;
}
Some(MilliTime {
milliday: ((hour * 3600 + minute * 60 + second) as f64 / 86.4).round() as u32,
})
}
pub fn from_naive_time(nt: chrono::NaiveTime) -> Self {
MilliTime {
milliday: (nt.num_seconds_from_midnight() as f64 / 86.4).round() as u32,
}
}
pub fn from_str(s: &str) -> Option<Self> {
if s.len() != 5 {
return None;
};
let milliday = s.get(0..3)?.parse::<u32>().ok()?;
let millis_unit = s.get(3..5)?;
if millis_unit != "md" {
return None;
};
Some(MilliTime { milliday })
}
pub fn milliday(&self) -> u32 {
self.milliday
}
pub fn to_naive_time(&self) -> Option<chrono::NaiveTime> {
chrono::NaiveTime::from_num_seconds_from_midnight_opt(
(self.milliday as f64 * 86.4).round() as u32,
0,
)
}
}
impl fmt::Display for MilliTime {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, r#"{:03}md"#, self.milliday)
}
}
#[cfg(test)]
mod test {
#[test]
pub fn t07_naive_time_to_millis() {
let nt = chrono::NaiveTime::from_hms_opt(13, 30, 00).unwrap();
let millis = super::MilliTime::from_naive_time(nt);
assert_eq!(millis.milliday, 563);
}
#[test]
pub fn t08_naive_time_to_millis_str() {
let nt = chrono::NaiveTime::from_hms_opt(13, 30, 00).unwrap();
let millis = super::MilliTime::from_naive_time(nt);
assert_eq!(millis.to_string(), "563md");
}
#[test]
pub fn t09_millis_from_str_opt() {
let millis = super::MilliTime::from_str("560md").unwrap();
assert_eq!(millis.milliday(), 560);
}
#[test]
#[should_panic]
pub fn t10_millis_from_str_opt_should_panic() {
let _millis = super::MilliTime::from_str("560 md").unwrap();
}
#[test]
pub fn t11_millis_to_naive_time_opt() {
let millis = super::MilliTime::from_str("560md").unwrap();
let nt = millis.to_naive_time().unwrap();
assert_eq!(nt, chrono::NaiveTime::from_hms_opt(13, 26, 24).unwrap());
}
}