use crate::{DateClassification, Token};
use alloc::string::String;
use alloc::vec;
use alloc::vec::Vec;
pub(crate) fn get_compatible_time_suffixes(class: &DateClassification) -> Vec<String> {
if !class.has_time {
let suff = build_zone_suffix(class);
return if suff.is_empty() {
Vec::new()
} else {
vec![suff]
};
}
let mut time_bases = build_time_bases(class);
let zone = build_zone_suffix(class);
if !zone.is_empty() {
for base in &mut time_bases {
base.push_str(&zone);
}
}
time_bases
}
fn build_zone_suffix(class: &DateClassification) -> String {
let tokens = &class.time_tokens;
if tokens.is_empty() {
return String::new();
}
let mut s = String::with_capacity(32);
let mut i = 0usize;
if i < tokens.len() && is_main_time_token(tokens[i]) {
i += 1;
}
while i < tokens.len() {
match tokens[i] {
Token::Pm | Token::Am => {
i += 1;
continue;
}
Token::Space => {
s.push(' ');
i += 1;
}
Token::Plus | Token::Minus => {
i += 1;
} Token::Offset => {
s.push_str("%z");
i += 1;
}
Token::OffsetColon => {
s.push_str("%:z");
i += 1;
}
Token::LBracket => {
s.push('[');
i += 1;
}
Token::RBracket => {
s.push(']');
i += 1;
}
Token::Iana => {
s.push_str("%Q");
i += 1;
}
Token::Zulu => {
s.push('Z');
i += 1;
}
_ => {
i += 1;
}
}
}
s
}
#[inline]
fn build_time_bases(class: &DateClassification) -> Vec<String> {
let tokens = &class.time_tokens;
if tokens.is_empty() {
return Vec::new();
}
let first = tokens[0];
let (has_seconds, time_sep) = match first {
Token::Hms | Token::HmsColon => (true, if first == Token::HmsColon { ":" } else { "" }),
Token::Hm | Token::HmColon => (false, if first == Token::HmColon { ":" } else { "" }),
_ => return Vec::new(),
};
let mut suffixes: Vec<String> = Vec::with_capacity(4);
let connector_str = class.connector.as_str();
let use_fractional = class.has_fractional;
let is_12h = class.has_ampm;
let include_extra = !use_fractional && class.is_pure_numeric;
let has_seconds_options: Vec<bool> = if use_fractional {
vec![true]
} else if include_extra {
if has_seconds {
vec![true, false]
} else {
vec![false, true]
}
} else {
vec![has_seconds]
};
if is_12h {
for &sec in &has_seconds_options {
let mut base = String::with_capacity(32);
base.push_str(connector_str);
base.push_str("%I");
base.push_str(time_sep);
base.push_str("%M");
if use_fractional {
base.push_str(time_sep);
base.push_str("%S%.f %p");
suffixes.push(base);
} else if sec {
base.push_str(time_sep);
base.push_str("%S %p");
suffixes.push(base);
} else {
base.push_str(" %p");
suffixes.push(base);
}
}
} else {
for hour in ["%H", "%k"] {
for &sec in &has_seconds_options {
let mut base = String::with_capacity(32);
base.push_str(connector_str);
base.push_str(hour);
base.push_str(time_sep);
base.push_str("%M");
if use_fractional {
base.push_str(time_sep);
base.push_str("%S%.f");
suffixes.push(base);
} else if sec {
base.push_str(time_sep);
base.push_str("%S");
suffixes.push(base);
} else {
suffixes.push(base);
}
}
}
}
suffixes
}
#[inline]
fn is_main_time_token(t: Token) -> bool {
matches!(t, Token::Hms | Token::HmsColon | Token::Hm | Token::HmColon)
}