use crate::parser::PestRule as Rule;
use crate::script_timezone::{ScriptTimezone, ScriptTimezoneParser};
use anyhow::Result;
use pest::iterators::Pair;
#[derive(Debug, PartialEq)]
pub enum Part {
None,
Pm,
Am,
}
#[derive(Debug, PartialEq, Copy, Clone)]
pub struct At {
pub hours: u32,
pub minutes: u32,
pub script_timezone: ScriptTimezone,
}
impl At {
fn convert_24h(hours: u32, minutes: u32, part: &Part) -> (u32, u32) {
let mut hours = hours;
match part {
Part::Pm => {
hours = match hours {
0 => 12,
1 => 13,
2 => 14,
3 => 15,
4 => 16,
5 => 17,
6 => 18,
7 => 19,
8 => 20,
9 => 21,
10 => 22,
11 => 23,
_ => hours,
};
}
_ => {}
}
if hours == 24 {
hours = 0;
}
if part == &Part::Am && hours == 12 {
hours = 0;
}
(hours, minutes)
}
pub fn parse(at_time_expr: Pair<Rule>) -> Result<Self> {
let mut hours = 0;
let mut minutes = 0;
let mut part = Part::None;
let mut script_timezone = ScriptTimezone::Mirror;
for expr in at_time_expr.into_inner() {
match expr.as_rule() {
Rule::AtTime => {
for prop in expr.into_inner() {
match prop.as_rule() {
Rule::Pm => part = Part::Pm,
Rule::Am => part = Part::Am,
Rule::AtHours => {
hours = prop
.as_str()
.parse()
.expect("could not parse {at hours} in script");
}
Rule::AtMinutes => {
minutes = prop
.as_str()
.parse()
.expect("could not parse {at minutes} in script");
}
_ => {}
}
}
}
Rule::TimezoneLikeExpr => {
let tz = ScriptTimezoneParser::parse(expr.as_str())?;
script_timezone = ScriptTimezone::Custom(tz);
}
_ => {}
}
}
let (hours, minutes) = Self::convert_24h(hours, minutes, &part);
Ok(Self {
hours,
minutes,
script_timezone,
})
}
}
#[cfg(test)]
mod convert_24h {
use super::{At, Part};
macro_rules! test {
(
$name:tt =>
$actual_h:literal:$actual_m:literal $part:tt
match
$expected_h:literal:$expected_m:literal
) => {
#[test]
fn $name() {
pretty_assertions::assert_eq!(
At::convert_24h($actual_h, $actual_m, &Part::$part),
($expected_h, $expected_m),
);
}
};
(
$name:tt =>
$actual_h:literal:$actual_m:literal
match
$expected_h:literal:$expected_m:literal
) => {
test! { $name => $actual_h:$actual_m None match $expected_h:$expected_m }
};
}
mod h12 {
use super::*;
mod am {
use super::*;
test! { _00_00 => 00:00 Am match 00:00 }
test! { _01_15 => 01:15 Am match 01:15 }
test! { _02_30 => 02:30 Am match 02:30 }
test! { _03_45 => 03:45 Am match 03:45 }
test! { _04_00 => 04:00 Am match 04:00 }
test! { _05_15 => 05:15 Am match 05:15 }
test! { _06_30 => 06:30 Am match 06:30 }
test! { _07_45 => 07:45 Am match 07:45 }
test! { _08_00 => 08:00 Am match 08:00 }
test! { _09_15 => 09:15 Am match 09:15 }
test! { _10_30 => 10:30 Am match 10:30 }
test! { _11_45 => 11:45 Am match 11:45 }
test! { _12_00 => 12:00 Am match 00:00 }
}
mod pm {
use super::*;
test! { _00_00 => 00:00 Pm match 12:00 }
test! { _01_15 => 01:15 Pm match 13:15 }
test! { _02_30 => 02:30 Pm match 14:30 }
test! { _03_45 => 03:45 Pm match 15:45 }
test! { _04_00 => 04:00 Pm match 16:00 }
test! { _05_15 => 05:15 Pm match 17:15 }
test! { _06_30 => 06:30 Pm match 18:30 }
test! { _07_45 => 07:45 Pm match 19:45 }
test! { _08_00 => 08:00 Pm match 20:00 }
test! { _09_15 => 09:15 Pm match 21:15 }
test! { _10_30 => 10:30 Pm match 22:30 }
test! { _11_45 => 11:45 Pm match 23:45 }
test! { _12_00 => 12:00 Pm match 12:00 }
}
mod weird {
use super::*;
mod am {
use super::*;
test! { _13_00 => 13:00 Am match 13:00 }
test! { _14_15 => 14:15 Am match 14:15 }
test! { _15_30 => 15:30 Am match 15:30 }
test! { _16_45 => 16:45 Am match 16:45 }
test! { _17_00 => 17:00 Am match 17:00 }
test! { _18_15 => 18:15 Am match 18:15 }
test! { _19_30 => 19:30 Am match 19:30 }
test! { _20_45 => 20:45 Am match 20:45 }
test! { _21_00 => 21:00 Am match 21:00 }
test! { _22_15 => 22:15 Am match 22:15 }
test! { _23_30 => 23:30 Am match 23:30 }
test! { _24_00 => 24:00 Am match 00:00 }
}
mod pm {
use super::*;
test! { _13_00 => 13:00 Pm match 13:00 }
test! { _14_15 => 14:15 Pm match 14:15 }
test! { _15_30 => 15:30 Pm match 15:30 }
test! { _16_45 => 16:45 Pm match 16:45 }
test! { _17_00 => 17:00 Pm match 17:00 }
test! { _18_15 => 18:15 Pm match 18:15 }
test! { _19_30 => 19:30 Pm match 19:30 }
test! { _20_45 => 20:45 Pm match 20:45 }
test! { _21_00 => 21:00 Pm match 21:00 }
test! { _22_15 => 22:15 Pm match 22:15 }
test! { _23_30 => 23:30 Pm match 23:30 }
test! { _24_00 => 24:00 Pm match 00:00 }
}
}
}
mod h24 {
use super::*;
test! { _00_00 => 00:00 match 00:00 }
test! { _01_15 => 01:15 match 01:15 }
test! { _02_30 => 02:30 match 02:30 }
test! { _03_45 => 03:45 match 03:45 }
test! { _04_00 => 04:00 match 04:00 }
test! { _05_15 => 05:15 match 05:15 }
test! { _06_30 => 06:30 match 06:30 }
test! { _07_45 => 07:45 match 07:45 }
test! { _08_00 => 08:00 match 08:00 }
test! { _09_15 => 09:15 match 09:15 }
test! { _10_30 => 10:30 match 10:30 }
test! { _11_45 => 11:45 match 11:45 }
test! { _12_00 => 12:00 match 12:00 }
test! { _13_15 => 13:15 match 13:15 }
test! { _14_30 => 14:30 match 14:30 }
test! { _15_45 => 15:45 match 15:45 }
test! { _16_00 => 16:00 match 16:00 }
test! { _17_15 => 17:15 match 17:15 }
test! { _18_30 => 18:30 match 18:30 }
test! { _19_45 => 19:45 match 19:45 }
test! { _20_00 => 20:00 match 20:00 }
test! { _21_15 => 21:15 match 21:15 }
test! { _22_30 => 22:30 match 22:30 }
test! { _23_45 => 23:45 match 23:45 }
test! { _24_00 => 24:00 match 00:00 }
}
}