use icu_locid::Locale;
use icu_provider::{DataProvider, DataRequest, ResourceOptions, ResourcePath};
use crate::{
date::ZonedDateTimeInput,
datetime::DateTimeFormat,
format::zoned_datetime::{self, FormattedZonedDateTime},
options::DateTimeFormatOptions,
provider::{self, helpers::DateTimePatterns},
time_zone::TimeZoneFormat,
DateTimeFormatError,
};
pub struct ZonedDateTimeFormat<'d> {
pub(super) datetime_format: DateTimeFormat<'d>,
pub(super) time_zone_format: TimeZoneFormat<'d>,
}
impl<'d> ZonedDateTimeFormat<'d> {
pub fn try_new<L, DP, ZP>(
locale: L,
date_provider: &DP,
zone_provider: &ZP,
options: &DateTimeFormatOptions,
) -> Result<Self, DateTimeFormatError>
where
L: Into<Locale>,
DP: DataProvider<'d, provider::gregory::DatesV1> + ?Sized,
ZP: DataProvider<'d, provider::time_zones::TimeZoneFormatsV1<'d>>
+ DataProvider<'d, provider::time_zones::ExemplarCitiesV1<'d>>
+ DataProvider<'d, provider::time_zones::MetaZoneGenericNamesLongV1<'d>>
+ DataProvider<'d, provider::time_zones::MetaZoneGenericNamesShortV1<'d>>
+ DataProvider<'d, provider::time_zones::MetaZoneSpecificNamesLongV1<'d>>
+ DataProvider<'d, provider::time_zones::MetaZoneSpecificNamesShortV1<'d>>
+ ?Sized,
{
let locale = locale.into();
let data = date_provider
.load_payload(&DataRequest {
resource_path: ResourcePath {
key: provider::key::GREGORY_V1,
options: ResourceOptions {
variant: None,
langid: Some(locale.clone().into()),
},
},
})?
.payload
.take()?;
let pattern = data
.patterns
.get_pattern_for_options(options)?
.unwrap_or_default();
let datetime_format = DateTimeFormat::new(locale, pattern, data);
let time_zone_format = TimeZoneFormat::try_new(
datetime_format.locale.clone(),
datetime_format.pattern.clone(),
zone_provider,
)?;
Ok(Self {
datetime_format,
time_zone_format,
})
}
pub fn format<'l: 'd, T>(&'l self, value: &'l T) -> FormattedZonedDateTime<'l, T>
where
T: ZonedDateTimeInput,
{
FormattedZonedDateTime {
zoned_datetime_format: self,
zoned_datetime: value,
}
}
pub fn format_to_write(
&self,
w: &mut impl std::fmt::Write,
value: &impl ZonedDateTimeInput,
) -> std::fmt::Result {
zoned_datetime::write_pattern(self, value, w).map_err(|_| std::fmt::Error)
}
pub fn format_to_string(&self, value: &impl ZonedDateTimeInput) -> String {
let mut s = String::new();
self.format_to_write(&mut s, value)
.expect("Failed to write to a String.");
s
}
}