From 1b065c434f552bcb878485fc1de260f0c2d5c273 Mon Sep 17 00:00:00 2001 From: xeruf <27jf@pm.me> Date: Wed, 18 Dec 2024 14:10:03 +0100 Subject: [PATCH] feat(helpers): parse HHMM timestamps --- src/helpers.rs | 62 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 53 insertions(+), 9 deletions(-) diff --git a/src/helpers.rs b/src/helpers.rs index 9438d24..a35b367 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -1,5 +1,3 @@ -use std::ops::Sub; - use chrono::LocalResult::Single; use chrono::{DateTime, Local, NaiveTime, TimeDelta, TimeZone, Utc}; use log::{debug, error, info, trace, warn}; @@ -34,16 +32,24 @@ impl ToTimestamp for DateTime { } } -/// Parses the hour from a plain number in the String, + +/// Parses the hour optionally with minute from a plain number in a String, /// with max of max_future hours into the future. -// TODO parse HHMM as well pub fn parse_hour(str: &str, max_future: i64) -> Option> { - str.parse::().ok().and_then(|hour| { - let now = Local::now(); + parse_hour_after(str, Local::now() - TimeDelta::hours(24 - max_future)) +} + +/// Parses the hour optionally with minute from a plain number in a String. +pub fn parse_hour_after(str: &str, after: DateTime) -> Option> { + str.parse::().ok().and_then(|number| { #[allow(deprecated)] - now.date().and_hms_opt(hour, 0, 0).map(|time| { - if time - now > TimeDelta::hours(max_future) { - time.sub(TimeDelta::days(1)) + after.date().and_hms_opt( + if number > 23 { number / 100 } else { number }, + if number > 23 { number % 100 } else { 0 }, + 0, + ).map(|time| { + if time < after { + time + TimeDelta::days(1) } else { time } @@ -160,3 +166,41 @@ pub fn format_timestamp_relative_to(stamp: &Timestamp, reference: &Timestamp) -> _ => format_timestamp_local(stamp), } } + +mod test { + use super::*; + use chrono::{NaiveDate, NaiveDateTime, Timelike}; + use interim::datetime::DateTime; + + #[test] + fn parse_hours() { + let now = Local::now(); + #[allow(deprecated)] + let date = now.date(); + if now.hour() > 2 { + assert_eq!( + parse_hour("23", 22).unwrap(), + date.and_hms_opt(23, 0, 0).unwrap() + ); + } + if now.hour() < 22 { + assert_eq!( + parse_hour("02", 2).unwrap(), + date.and_hms_opt(2, 0, 0).unwrap() + ); + assert_eq!( + parse_hour("2301", 1).unwrap(), + (date - TimeDelta::days(1)).and_hms_opt(23, 01, 0).unwrap() + ); + } + + let date = NaiveDate::from_ymd_opt(2020, 10, 10).unwrap(); + let time = Utc.from_utc_datetime( + &date.and_hms_opt(10, 1,0).unwrap() + ); + assert_eq!(parse_hour_after("2201", time).unwrap(), Utc.from_utc_datetime(&date.and_hms_opt(22, 1, 0).unwrap())); + assert_eq!(parse_hour_after("10", time).unwrap(), Utc.from_utc_datetime(&(date + TimeDelta::days(1)).and_hms_opt(10, 0, 0).unwrap())); + + // TODO test timezone offset issues + } +} \ No newline at end of file