#[cfg(feature = "locale")]
use crate::locale_prefers_day_first;
use crate::{ConnectorType, DateClassification, DateToken, DetectedDateOrder};
#[inline]
pub(crate) fn smart_detect_date_order(s: &str, class: &DateClassification) -> DetectedDateOrder {
if class.is_pure_numeric && class.num_digits >= 6 {
return DetectedDateOrder::YearFirst;
}
let s = s.trim_start_matches(|c: char| c == '+' || c == '-');
if matches!(class.tokens.first(), Some(DateToken::Digits(n)) if *n >= 4) {
if let Some(year_candidate) = s.get(0..4).and_then(|p| p.parse::<u16>().ok()) {
if (1900..=2100).contains(&year_candidate) {
return DetectedDateOrder::YearFirst;
}
}
}
let mut num_iter = s
.split(|c: char| matches!(c, '/' | '-' | '.' | ' ' | 'T'))
.filter_map(|p| {
let p = p.trim();
if p.is_empty() {
None
} else {
p.parse::<u32>().ok()
}
});
let first = num_iter.next().unwrap_or(0);
if first > 12 && first <= 31 {
return DetectedDateOrder::DayFirst;
}
let second = if first >= 1 && first <= 12 {
num_iter.next().unwrap_or(0)
} else {
0
};
if second > 12 && second <= 31 {
return DetectedDateOrder::MonthFirst;
}
if class.connector == ConnectorType::UpperT || class.has_offset_or_zone() {
return DetectedDateOrder::YearFirst;
}
#[cfg(feature = "locale")]
{
if locale_prefers_day_first() {
DetectedDateOrder::DayFirst
} else {
DetectedDateOrder::MonthFirst
}
}
#[cfg(not(feature = "locale"))]
{
DetectedDateOrder::DayFirst
}
}