use crate::cldr_serde;
use icu::datetime::provider::day_periods::*;
use icu_provider::prelude::*;
use std::borrow::Cow;
pub(crate) fn compute_day_periods<'a>(
rules: &std::collections::BTreeMap<String, cldr_serde::day_periods::DayPeriodRule>,
names: &'a std::collections::BTreeMap<String, Cow<'a, str>>,
locale: DataLocale,
) -> Result<(DayPeriodRules, impl Iterator<Item = &'a str>), DataError> {
fn parse_hour(s: &str) -> u8 {
let mut parts = s.split(':');
let hour = parts.next().unwrap().parse().unwrap();
if let Some(min_str) = parts.next() {
let min: u32 = min_str.parse().unwrap();
if min != 0 {
log::warn!(
"Non-zero minute found in day period time: {}, precision will be lost",
s
);
}
}
hour
}
let mut entries = std::collections::BTreeMap::new();
for (period, rule) in rules {
if rule.at.is_some() {
assert!(
period == "noon" || period == "midnight",
"Found 'at' rule for non-noon/midnight period: {} in locale {}",
period,
locale
);
}
if let Some(name) = names.get(period) {
if let (Some(from), Some(before)) = (&rule.from, &rule.before) {
let start = parse_hour(from);
let end = parse_hour(before);
entries.insert((start, end), &**name);
} else {
log::warn!("Did not have from/before values for rule {period} in locale {locale}")
}
} else if period != "morning" && period != "afternoon" {
log::warn!("missing name for range {period} in locale {locale}");
}
}
DayPeriodRules::from_periods(entries).map_err(|e| {
DataError::custom("day period rules")
.with_debug_context(&locale)
.with_display_context(e)
})
}
#[cfg(test)]
mod tests {
use super::*;
use crate::cldr_serde::day_periods::DayPeriodRule;
use std::collections::BTreeMap;
#[test]
fn test_compute_day_periods() {
let mut rules = BTreeMap::new();
let mut names = BTreeMap::new();
rules.insert(
"morning1".to_string(),
DayPeriodRule {
from: Some("06:00".to_string()),
before: Some("12:00".to_string()),
at: None,
},
);
names.insert(String::from("morning1"), Cow::Borrowed("foo"));
rules.insert(
"afternoon1".to_string(),
DayPeriodRule {
from: Some("12:00".to_string()),
before: Some("18:00".to_string()),
at: None,
},
);
names.insert(String::from("afternoon1"), Cow::Borrowed("bar"));
rules.insert(
"evening1".to_string(),
DayPeriodRule {
from: Some("18:00".to_string()),
before: Some("21:00".to_string()),
at: None,
},
);
names.insert(String::from("evening1"), Cow::Borrowed("baz"));
rules.insert(
"night1".to_string(),
DayPeriodRule {
from: Some("21:00".to_string()),
before: Some("06:00".to_string()),
at: None,
},
);
names.insert(String::from("night1"), Cow::Borrowed("qux"));
let actual = compute_day_periods(&rules, &names, Default::default()).unwrap();
let expected = DayPeriodRules::from_periods(
[
((6, 12), "foo"),
((12, 18), "bar"),
((18, 21), "baz"),
((21, 6), "qux"),
]
.into_iter()
.collect(),
)
.unwrap();
assert_eq!(actual.0, expected.0);
assert_eq!(actual.1.collect::<Vec<_>>(), expected.1.collect::<Vec<_>>());
}
}