From 9849bfe7bf44c6f5cac34fad24fa351c4e3998c7 Mon Sep 17 00:00:00 2001 From: cos Date: Sat, 3 Jul 2021 17:09:24 +0200 Subject: Correct 24h time While respecting that there is one culture which has colonized this planet, as well as managed to make its language the lingua franca of the contemporary world, its typical use of 12h time can not excuse going as wild with "parsing English time expressions" as this crate does prior to this commit. One might consult https://en.wikipedia.org/wiki/24-hour_clock to learn about reasonable expectations. Specifically, this fixes the bugs: * No times during the interval 00:00-00:59 were allowed. * The time 24:00 was considered 00:00, of the wrong (preceeding) day. * Bogus times in the interval 24:00-24:59 were allowed. After this commit 24:00 becomes an invalid time. Correctly rewriting it to 00:00, with overflow to the next day, is left as an excercise to whoever feels strongly enough for that edge functionality. --- src/lib.rs | 9 ++------- tests/tests.rs | 38 ++++++++++++++++++++++++++++++-------- 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index c0fc1ad..91aa73b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -354,7 +354,7 @@ lazy_static! { end => ("end") from_now_or_ago => [["from now", "ago"]] h12 => (?-B) [(1..=12).into_iter().collect::>()] - h24 => [(1..=24).into_iter().flat_map(|i| vec![format!("{}", i), format!("{:02}", i)]).collect::>()] + h24 => [(0..24).into_iter().flat_map(|i| vec![format!("{}", i), format!("{:02}", i)]).collect::>()] minute => (?-B) [ (0..60).into_iter().map(|i| format!("{:02}", i)).collect::>() ] modifier => [["the", "this", "last", "next"]] named_time => [["noon", "midnight"]] @@ -1518,12 +1518,7 @@ fn time(m: &Match) -> (u32, u32, u32, bool) { }; } let hour = if let Some(hour_24) = m.name("hour_24") { - let hour = s_to_n(hour_24.name("h24").unwrap().as_str()); - if hour == 24 { - 0 - } else { - hour - } + s_to_n(hour_24.name("h24").unwrap().as_str()) } else if let Some(hour_12) = m.name("hour_12") { let mut hour = s_to_n(hour_12.name("h12").unwrap().as_str()); hour = if let Some(am_pm) = m.name("am_pm") { diff --git a/tests/tests.rs b/tests/tests.rs index a2852d8..1c593be 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -1587,18 +1587,40 @@ fn simple_noon_past_and_future() { fn midnight() { let d1 = NaiveDate::from_ymd(1969, 5, 7).and_hms(0, 0, 0); let d2 = d1 + Duration::seconds(1); - match parse("midnight on May 6, 1969", None) { - Ok((start, end, _)) => { - assert_eq!(d1, start); - assert_eq!(d2, end); - } - Err(e) => { - println!("{:?}", e); - assert!(false, "didn't match"); + for phrase in [ + "midnight on May 6, 1969", + // TODO Add 12h representation, whichever is considered midnight?! + // Possible am/pm might differ between GB and some colonial time + // representations, just as an imperial gallon is roughly 4.5 + // litres while a US gallon is not even 3.8 liters. + "00:00 on May 7, 1969", ].iter() + { + match parse(phrase, None) { + Ok((start, end, _)) => { + assert_eq!(d1, start); + assert_eq!(d2, end); + } + Err(e) => { + println!("{:?}", e); + assert!(false, "didn't match"); + } } } } +#[test] +fn invalid_24_00() { + // While 24:00 might arguably be an ok time, is not implemented in this crate. + let phrase = "24:00"; + assert!(parse(phrase, None).is_err()); +} + +#[test] +fn super_invalid_24_30() { + let phrase = "24:30"; + assert!(parse(phrase, None).is_err()); +} + #[derive(Debug)] enum Period { Week, -- cgit v1.2.3