#[diplomat::bridge]
#[diplomat::abi_rename = "icu4x_{0}_mv1"]
#[diplomat::attr(auto, namespace = "icu4x")]
pub mod ffi {
use alloc::boxed::Box;
use icu_datetime::{fieldset::YMDTV, options::NeoSkeletonLength};
use icu_timezone::ZoneVariant;
use crate::{
datetime::ffi::{DateTime, IsoDateTime},
datetime_formatter::ffi::DateTimeLength,
errors::ffi::{DateTimeFormatError, PatternLoadError},
locale_core::ffi::Locale,
provider::ffi::DataProvider,
timezone::ffi::TimeZoneInfo,
};
use writeable::TryWriteable;
#[diplomat::opaque]
#[diplomat::rust_link(icu::datetime, Mod)]
pub struct GregorianZonedDateTimeFormatter(
pub icu_datetime::FixedCalendarDateTimeFormatter<icu_calendar::Gregorian, YMDTV>,
);
impl GregorianZonedDateTimeFormatter {
#[diplomat::attr(supports = fallible_constructors, named_constructor = "with_length")]
#[diplomat::demo(default_constructor)]
pub fn create_with_length(
provider: &DataProvider,
locale: &Locale,
length: DateTimeLength,
) -> Result<Box<GregorianZonedDateTimeFormatter>, PatternLoadError> {
let locale = locale.to_datalocale();
let options = YMDTV::with_length(NeoSkeletonLength::from(length));
Ok(Box::new(GregorianZonedDateTimeFormatter(
call_constructor!(
icu_datetime::FixedCalendarDateTimeFormatter::try_new,
icu_datetime::FixedCalendarDateTimeFormatter::try_new_with_any_provider,
icu_datetime::FixedCalendarDateTimeFormatter::try_new_with_buffer_provider,
provider,
&locale,
options
)?,
)))
}
pub fn format_iso_datetime_with_custom_time_zone(
&self,
datetime: &IsoDateTime,
time_zone: &TimeZoneInfo,
write: &mut diplomat_runtime::DiplomatWrite,
) -> Result<(), DateTimeFormatError> {
let greg = icu_calendar::DateTime::new_from_iso(datetime.0, icu_calendar::Gregorian);
let zdt = icu_timezone::CustomZonedDateTime {
date: greg.date,
time: greg.time,
zone: time_zone
.time_zone_id
.with_offset(time_zone.offset)
.at_time((datetime.0.date, datetime.0.time))
.with_zone_variant(time_zone.zone_variant.unwrap_or(ZoneVariant::Standard)),
};
let _lossy = self.0.format(&zdt).try_write_to(write);
Ok(())
}
}
#[diplomat::opaque]
#[diplomat::rust_link(icu::datetime, Mod)]
pub struct ZonedDateTimeFormatter(pub icu_datetime::DateTimeFormatter<YMDTV>);
impl ZonedDateTimeFormatter {
#[diplomat::attr(supports = fallible_constructors, named_constructor = "with_length")]
#[diplomat::demo(default_constructor)]
pub fn create_with_length(
provider: &DataProvider,
locale: &Locale,
length: DateTimeLength,
) -> Result<Box<ZonedDateTimeFormatter>, PatternLoadError> {
let locale = locale.to_datalocale();
let options = YMDTV::with_length(NeoSkeletonLength::from(length));
Ok(Box::new(ZonedDateTimeFormatter(call_constructor!(
icu_datetime::DateTimeFormatter::try_new,
icu_datetime::DateTimeFormatter::try_new_with_any_provider,
icu_datetime::DateTimeFormatter::try_new_with_buffer_provider,
provider,
&locale,
options,
)?)))
}
pub fn format_datetime_with_custom_time_zone(
&self,
datetime: &DateTime,
time_zone: &TimeZoneInfo,
write: &mut diplomat_runtime::DiplomatWrite,
) -> Result<(), DateTimeFormatError> {
let zdt = icu_timezone::CustomZonedDateTime {
date: datetime.0.date.clone(),
time: datetime.0.time,
zone: time_zone
.time_zone_id
.with_offset(time_zone.offset)
.at_time((datetime.0.date.to_iso(), datetime.0.time))
.with_zone_variant(
time_zone
.zone_variant
.ok_or(DateTimeFormatError::ZoneInfoMissingFields)?,
),
};
let _lossy = self.0.convert_and_format(&zdt).try_write_to(write);
Ok(())
}
pub fn format_iso_datetime_with_custom_time_zone(
&self,
datetime: &IsoDateTime,
time_zone: &TimeZoneInfo,
write: &mut diplomat_runtime::DiplomatWrite,
) -> Result<(), DateTimeFormatError> {
let zdt = icu_timezone::CustomZonedDateTime {
date: datetime.0.date,
time: datetime.0.time,
zone: time_zone
.time_zone_id
.with_offset(time_zone.offset)
.at_time((datetime.0.date, datetime.0.time))
.with_zone_variant(time_zone.zone_variant.unwrap_or(ZoneVariant::Standard)),
};
let _lossy = self.0.convert_and_format(&zdt).try_write_to(write);
Ok(())
}
}
}