use crate::{
format::datetime,
options::DateTimeFormatOptions,
provider::{
gregory::{DatePatternsV1Marker, DateSymbolsV1Marker},
helpers::DateTimePatterns,
},
};
use alloc::string::String;
use icu_locid::Locale;
use icu_provider::prelude::*;
use crate::{
date::DateTimeInput, pattern::Pattern, provider, DateTimeFormatError, FormattedDateTime,
};
pub struct DateTimeFormat<'data> {
pub(super) locale: Locale,
pub(super) pattern: Pattern,
pub(super) symbols: Option<DataPayload<'data, DateSymbolsV1Marker>>,
}
impl<'data> DateTimeFormat<'data> {
pub fn try_new<
T: Into<Locale>,
D: DataProvider<'data, DateSymbolsV1Marker>
+ DataProvider<'data, DatePatternsV1Marker>
+ ?Sized,
>(
locale: T,
data_provider: &D,
options: &DateTimeFormatOptions,
) -> Result<Self, DateTimeFormatError> {
let locale = locale.into();
let patterns_data: icu_provider::DataPayload<'_, provider::gregory::DatePatternsV1Marker> =
data_provider
.load_payload(&DataRequest {
resource_path: ResourcePath {
key: provider::key::GREGORY_DATE_PATTERNS_V1,
options: ResourceOptions {
variant: None,
langid: Some(locale.clone().into()),
},
},
})?
.take_payload()?;
let pattern = patterns_data
.get()
.get_pattern_for_options(options)?
.unwrap_or_default();
let requires_data = datetime::analyze_pattern(&pattern, false)
.map_err(|field| DateTimeFormatError::UnsupportedField(field.symbol))?;
let symbols_data = if requires_data {
Some(
data_provider
.load_payload(&DataRequest {
resource_path: ResourcePath {
key: provider::key::GREGORY_DATE_SYMBOLS_V1,
options: ResourceOptions {
variant: None,
langid: Some(locale.clone().into()),
},
},
})?
.take_payload()?,
)
} else {
None
};
Ok(Self::new(locale, pattern, symbols_data))
}
pub(super) fn new<T: Into<Locale>>(
locale: T,
pattern: Pattern,
symbols: Option<DataPayload<'data, DateSymbolsV1Marker>>,
) -> Self {
let locale = locale.into();
Self {
locale,
pattern,
symbols,
}
}
pub fn format<'l, T>(&'l self, value: &'l T) -> FormattedDateTime<'l, T>
where
T: DateTimeInput,
{
FormattedDateTime {
pattern: &self.pattern,
symbols: self.symbols.as_ref().map(|s| s.get()),
datetime: value,
locale: &self.locale,
}
}
pub fn format_to_write(
&self,
w: &mut impl core::fmt::Write,
value: &impl DateTimeInput,
) -> core::fmt::Result {
datetime::write_pattern(
&self.pattern,
self.symbols.as_ref().map(|s| s.get()),
value,
&self.locale,
w,
)
.map_err(|_| core::fmt::Error)
}
pub fn format_to_string(&self, value: &impl DateTimeInput) -> String {
let mut s = String::new();
self.format_to_write(&mut s, value)
.expect("Failed to write to a String.");
s
}
}