use crate::{
options::{length, preferences, DateTimeFormatterOptions},
provider::calendar::{TimeLengthsV1Marker, TimeSymbolsV1Marker},
provider::date_time::PatternSelector,
raw,
};
use alloc::string::String;
use core::marker::PhantomData;
use icu_calendar::provider::WeekDataV1Marker;
use icu_decimal::provider::DecimalSymbolsV1Marker;
use icu_plurals::provider::OrdinalV1Marker;
use icu_provider::prelude::*;
use writeable::Writeable;
use crate::{
calendar, input::DateInput, input::DateTimeInput, input::IsoTimeInput, CldrCalendar,
DateTimeError, FormattedDateTime,
};
#[derive(Debug)]
pub struct TimeFormatter(pub(super) raw::TimeFormatter);
impl TimeFormatter {
#[cfg(feature = "compiled_data")]
pub fn try_new_with_length(
locale: &DataLocale,
length: length::Time,
) -> Result<Self, DateTimeError> {
let preferences = Some(preferences::Bag::from_data_locale(locale));
Ok(Self(raw::TimeFormatter::try_new(
locale,
length,
preferences,
)?))
}
icu_provider::gen_any_buffer_data_constructors!(
locale: include,
length: length::Time,
error: DateTimeError,
#[cfg(skip)]
functions: [
try_new_with_length,
try_new_with_length_with_any_provider,
try_new_with_length_with_buffer_provider,
try_new_with_length_unstable,
Self,
]
);
#[inline]
#[doc = icu_provider::gen_any_buffer_unstable_docs!(UNSTABLE, Self::try_new_with_length)]
pub fn try_new_with_length_unstable<D>(
provider: &D,
locale: &DataLocale,
length: length::Time,
) -> Result<Self, DateTimeError>
where
D: DataProvider<TimeLengthsV1Marker>
+ DataProvider<TimeSymbolsV1Marker>
+ DataProvider<DecimalSymbolsV1Marker>
+ ?Sized,
{
let preferences = Some(preferences::Bag::from_data_locale(locale));
Ok(Self(raw::TimeFormatter::try_new_unstable(
provider,
locale,
length,
preferences,
)?))
}
#[inline]
pub fn format<'l, T>(&'l self, value: &T) -> FormattedDateTime<'l>
where
T: IsoTimeInput,
{
self.0.format(value)
}
#[inline]
pub fn format_to_string(&self, value: &impl IsoTimeInput) -> String {
self.format(value).write_to_string().into_owned()
}
}
#[derive(Debug)]
pub struct TypedDateFormatter<C>(pub(super) raw::DateFormatter, PhantomData<C>);
impl<C: CldrCalendar> TypedDateFormatter<C> {
#[cfg(feature = "compiled_data")]
pub fn try_new_with_length(
locale: &DataLocale,
length: length::Date,
) -> Result<Self, DateTimeError>
where
crate::provider::Baked: icu_provider::DataProvider<<C as CldrCalendar>::DateLengthsV1Marker>
+ icu_provider::DataProvider<<C as CldrCalendar>::DateSymbolsV1Marker>,
{
Ok(Self(
raw::DateFormatter::try_new(
calendar::load_lengths_for_cldr_calendar::<C, _>(&crate::provider::Baked, locale)?,
|| {
calendar::load_symbols_for_cldr_calendar::<C, _>(
&crate::provider::Baked,
locale,
)
},
locale,
length,
)?,
PhantomData,
))
}
icu_provider::gen_any_buffer_data_constructors!(
locale: include,
length: length::Date,
error: DateTimeError,
#[cfg(skip)]
functions: [
try_new_with_length,
try_new_with_length_with_any_provider,
try_new_with_length_with_buffer_provider,
try_new_with_length_unstable,
Self,
]
);
#[inline]
#[doc = icu_provider::gen_any_buffer_unstable_docs!(UNSTABLE, Self::try_new_with_length)]
pub fn try_new_with_length_unstable<D>(
provider: &D,
locale: &DataLocale,
length: length::Date,
) -> Result<Self, DateTimeError>
where
D: DataProvider<<C as CldrCalendar>::DateSymbolsV1Marker>
+ DataProvider<<C as CldrCalendar>::DateLengthsV1Marker>
+ DataProvider<DecimalSymbolsV1Marker>
+ DataProvider<OrdinalV1Marker>
+ DataProvider<WeekDataV1Marker>
+ ?Sized,
{
Ok(Self(
raw::DateFormatter::try_new_unstable(
provider,
calendar::load_lengths_for_cldr_calendar::<C, _>(provider, locale)?,
|| calendar::load_symbols_for_cldr_calendar::<C, _>(provider, locale),
locale,
length,
)?,
PhantomData,
))
}
#[inline]
pub fn format<'l, T>(&'l self, value: &T) -> FormattedDateTime<'l>
where
T: DateInput<Calendar = C>,
{
self.0.format(value)
}
#[inline]
pub fn format_to_string(&self, value: &impl DateInput<Calendar = C>) -> String {
self.format(value).write_to_string().into_owned()
}
}
#[derive(Debug)]
pub struct TypedDateTimeFormatter<C>(pub(super) raw::DateTimeFormatter, PhantomData<C>);
impl<C: CldrCalendar> TypedDateTimeFormatter<C> {
#[inline]
pub fn try_from_date_and_time(
date: TypedDateFormatter<C>,
time: TimeFormatter,
) -> Result<Self, DateTimeError>
where {
Ok(Self(
raw::DateTimeFormatter::try_from_date_and_time(date.0, time.0)?,
PhantomData,
))
}
#[cfg(feature = "compiled_data")]
pub fn try_new(
locale: &DataLocale,
options: DateTimeFormatterOptions,
) -> Result<Self, DateTimeError>
where
crate::provider::Baked: DataProvider<<C as CldrCalendar>::DateLengthsV1Marker>,
crate::provider::Baked: DataProvider<<C as CldrCalendar>::DateSymbolsV1Marker>,
{
let patterns = PatternSelector::for_options(
&crate::provider::Baked,
calendar::load_lengths_for_cldr_calendar::<C, _>(&crate::provider::Baked, locale)?,
locale,
&options,
)?;
Ok(Self(
raw::DateTimeFormatter::try_new(
patterns,
|| {
calendar::load_symbols_for_cldr_calendar::<C, _>(
&crate::provider::Baked,
locale,
)
},
locale,
)?,
PhantomData,
))
}
icu_provider::gen_any_buffer_data_constructors!(
locale: include,
options: DateTimeFormatterOptions,
error: DateTimeError,
#[cfg(skip)]
functions: [
try_new,
try_new_with_any_provider,
try_new_with_buffer_provider,
try_new_unstable,
Self
]
);
#[inline]
#[doc = icu_provider::gen_any_buffer_unstable_docs!(UNSTABLE, Self::try_new)]
pub fn try_new_unstable<D>(
provider: &D,
locale: &DataLocale,
options: DateTimeFormatterOptions,
) -> Result<Self, DateTimeError>
where
D: DataProvider<<C as CldrCalendar>::DateSymbolsV1Marker>
+ DataProvider<<C as CldrCalendar>::DateLengthsV1Marker>
+ DataProvider<TimeSymbolsV1Marker>
+ DataProvider<TimeLengthsV1Marker>
+ DataProvider<DecimalSymbolsV1Marker>
+ DataProvider<OrdinalV1Marker>
+ DataProvider<WeekDataV1Marker>
+ ?Sized,
{
let patterns = PatternSelector::for_options(
provider,
calendar::load_lengths_for_cldr_calendar::<C, _>(provider, locale)?,
locale,
&options,
)?;
Ok(Self(
raw::DateTimeFormatter::try_new_unstable(
provider,
patterns,
|| calendar::load_symbols_for_cldr_calendar::<C, _>(provider, locale),
locale,
)?,
PhantomData,
))
}
#[cfg(feature = "experimental")]
#[inline]
#[cfg(feature = "compiled_data")]
pub fn try_new_experimental(
locale: &DataLocale,
options: DateTimeFormatterOptions,
) -> Result<Self, DateTimeError>
where
crate::provider::Baked: DataProvider<<C as CldrCalendar>::DateLengthsV1Marker>,
crate::provider::Baked: DataProvider<<C as CldrCalendar>::DateSymbolsV1Marker>,
{
let patterns = PatternSelector::for_options_experimental(
&crate::provider::Baked,
calendar::load_lengths_for_cldr_calendar::<C, _>(&crate::provider::Baked, locale)?,
locale,
&C::DEFAULT_BCP_47_IDENTIFIER,
&options,
)?;
Ok(Self(
raw::DateTimeFormatter::try_new(
patterns,
|| {
calendar::load_symbols_for_cldr_calendar::<C, _>(
&crate::provider::Baked,
locale,
)
},
locale,
)?,
PhantomData,
))
}
#[doc = icu_provider::gen_any_buffer_unstable_docs!(UNSTABLE, Self::try_new_experimental)]
#[cfg(feature = "experimental")]
#[inline]
pub fn try_new_experimental_unstable<D>(
provider: &D,
locale: &DataLocale,
options: DateTimeFormatterOptions,
) -> Result<Self, DateTimeError>
where
D: DataProvider<<C as CldrCalendar>::DateSymbolsV1Marker>
+ DataProvider<<C as CldrCalendar>::DateLengthsV1Marker>
+ DataProvider<TimeSymbolsV1Marker>
+ DataProvider<TimeLengthsV1Marker>
+ DataProvider<crate::provider::calendar::DateSkeletonPatternsV1Marker>
+ DataProvider<DecimalSymbolsV1Marker>
+ DataProvider<OrdinalV1Marker>
+ DataProvider<WeekDataV1Marker>
+ ?Sized,
{
let patterns = PatternSelector::for_options_experimental(
provider,
calendar::load_lengths_for_cldr_calendar::<C, _>(provider, locale)?,
locale,
&C::DEFAULT_BCP_47_IDENTIFIER,
&options,
)?;
Ok(Self(
raw::DateTimeFormatter::try_new_unstable(
provider,
patterns,
|| calendar::load_symbols_for_cldr_calendar::<C, _>(provider, locale),
locale,
)?,
PhantomData,
))
}
#[inline]
pub fn format<'l, T>(&'l self, value: &T) -> FormattedDateTime<'l>
where
T: DateTimeInput<Calendar = C>,
{
self.0.format(value)
}
#[inline]
pub fn format_to_string(&self, value: &impl DateTimeInput<Calendar = C>) -> String {
self.format(value).write_to_string().into_owned()
}
#[cfg(feature = "experimental")]
pub fn resolve_components(&self) -> crate::options::components::Bag {
self.0.resolve_components()
}
}
#[cfg(test)]
#[cfg(feature = "serde")]
mod tests {
use super::*;
use icu_calendar::DateTime;
use icu_calendar::Gregorian;
#[test]
fn works_with_default_options() {
assert_eq!(
TypedDateTimeFormatter::<Gregorian>::try_new(Default::default(), Default::default(),)
.unwrap()
.format_to_string(
&DateTime::try_new_gregorian_datetime(2022, 9, 20, 0, 0, 0).unwrap()
),
"2022 M09 20 00:00:00"
);
}
}