// This file is part of ICU4X. For terms of use, please see the file // called LICENSE at the top level of the ICU4X source tree // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). use ffi::TimeZoneInfo; #[diplomat::bridge] #[diplomat::abi_rename = "icu4x_{0}_mv1"] pub mod ffi { use alloc::boxed::Box; use crate::unstable::{ date::ffi::IsoDate, datetime::ffi::IsoDateTime, time::ffi::Time, variant_offset::ffi::UtcOffset, }; #[diplomat::opaque] #[diplomat::rust_link(icu::time::TimeZone, Struct)] pub struct TimeZone(pub(crate) icu_time::TimeZone); impl TimeZone { /// The unknown time zone. #[diplomat::rust_link(icu::time::TimeZoneInfo::unknown, FnInStruct)] #[diplomat::rust_link(icu::time::TimeZone::unknown, FnInStruct, hidden)] #[diplomat::attr(auto, named_constructor)] pub fn unknown() -> Box { Box::new(TimeZone(icu_time::TimeZone::UNKNOWN)) } /// Whether the time zone is the unknown zone. #[diplomat::rust_link(icu::time::TimeZone::is_unknown, FnInStruct)] pub fn is_unknown(&self) -> bool { self.0.is_unknown() } /// Creates a time zone from a BCP-47 string. /// /// Returns the unknown time zone if the string is not a valid BCP-47 subtag. #[diplomat::rust_link(icu::time::TimeZone, Struct, compact)] #[diplomat::attr(auto, named_constructor = "from_bcp47")] #[diplomat::demo(default_constructor)] pub fn create_from_bcp47(id: &DiplomatStr) -> Box { icu_locale_core::subtags::Subtag::try_from_utf8(id) .map(icu_time::TimeZone) .map(TimeZone) .map(Box::new) .unwrap_or(Self::unknown()) } #[diplomat::rust_link(icu::time::TimeZone::with_offset, FnInStruct)] pub fn with_offset(&self, offset: &UtcOffset) -> Box { Box::new(self.0.with_offset(Some(offset.0)).into()) } #[diplomat::rust_link(icu::time::TimeZone::without_offset, FnInStruct)] pub fn without_offset(&self) -> Box { Box::new(self.0.without_offset().into()) } } #[diplomat::enum_convert(icu_time::zone::TimeZoneVariant, needs_wildcard)] #[diplomat::rust_link(icu::time::zone::TimeZoneVariant, Enum)] #[non_exhaustive] #[deprecated(note = "type not needed anymore")] pub enum TimeZoneVariant { // TimeZoneVariant in Rust doesn't have a default, but it is useful to have one // here for consistent behavior. #[diplomat::attr(auto, default)] Standard, Daylight, } #[allow(deprecated)] impl TimeZoneVariant { #[diplomat::rust_link(icu::time::zone::TimeZoneVariant::from_rearguard_isdst, FnInEnum)] #[diplomat::rust_link(icu::time::TimeZoneInfo::with_variant, FnInStruct)] #[deprecated(note = "type not needed anymore")] #[allow(deprecated)] // remove in 3.0 pub fn from_rearguard_isdst(isdst: bool) -> Self { icu_time::zone::TimeZoneVariant::from_rearguard_isdst(isdst).into() } } #[diplomat::opaque] #[diplomat::rust_link(icu::time::TimeZoneInfo, Struct)] #[diplomat::rust_link(icu::time::zone::models::AtTime, Struct, hidden)] #[diplomat::rust_link(icu::time::zone::models::Base, Struct, hidden)] #[diplomat::rust_link(icu::time::zone::models::Full, Struct, hidden)] #[derive(Clone, Copy)] pub struct TimeZoneInfo { pub(crate) id: icu_time::TimeZone, pub(crate) offset: Option, pub(crate) zone_name_timestamp: Option, } impl TimeZoneInfo { /// Creates a time zone for UTC (Coordinated Universal Time). #[diplomat::rust_link(icu::time::TimeZoneInfo::utc, FnInStruct)] #[diplomat::rust_link(icu::time::zone::UtcOffset::zero, FnInStruct, hidden)] #[diplomat::attr(auto, named_constructor)] pub fn utc() -> Box { Box::new(icu_time::TimeZoneInfo::utc().into()) } /// Creates a time zone info from parts. /// /// `variant` is ignored. #[diplomat::attr(auto, constructor)] #[allow(deprecated)] pub fn from_parts( id: &TimeZone, offset: Option<&UtcOffset>, _variant: Option, ) -> Box { Box::new(Self { id: id.0, offset: offset.map(|o| o.0), zone_name_timestamp: None, }) } #[diplomat::rust_link(icu::time::TimeZoneInfo::id, FnInStruct)] #[diplomat::attr(demo_gen, disable)] // this just returns a constructor argument #[diplomat::attr(auto, getter)] pub fn id(&self) -> Box { Box::new(TimeZone(self.id)) } /// Sets the datetime at which to interpret the time zone /// for display name lookup. /// /// Notes: /// /// - If not set, the formatting datetime is used if possible. /// - If the offset is not set, the datetime is interpreted as UTC. /// - The constraints are the same as with `ZoneNameTimestamp` in Rust. /// - Set to year 1000 or 9999 for a reference far in the past or future. #[diplomat::rust_link(icu::time::TimeZoneInfo::at_date_time_iso, FnInStruct)] #[diplomat::rust_link(icu::time::zone::ZoneNameTimestamp, Struct, compact)] #[diplomat::rust_link( icu::time::TimeZoneInfo::with_zone_name_timestamp, FnInStruct, hidden )] #[diplomat::rust_link( icu::time::zone::ZoneNameTimestamp::from_date_time_iso, FnInStruct, hidden )] #[diplomat::rust_link( icu::time::zone::ZoneNameTimestamp::far_in_future, FnInStruct, hidden )] // documented #[diplomat::rust_link(icu::time::zone::ZoneNameTimestamp::far_in_past, FnInStruct, hidden)] // documented pub fn at_date_time_iso(&self, date: &IsoDate, time: &Time) -> Box { Box::new(Self { zone_name_timestamp: Some( icu_time::zone::ZoneNameTimestamp::from_zoned_date_time_iso( icu_time::ZonedDateTime { date: date.0, time: time.0, zone: self.offset.unwrap_or(icu_time::zone::UtcOffset::zero()), }, ), ), ..*self }) } /// Sets the timestamp, in milliseconds since Unix epoch, at which to interpret the time zone /// for display name lookup. /// /// Notes: /// /// - If not set, the formatting datetime is used if possible. /// - The constraints are the same as with `ZoneNameTimestamp` in Rust. #[diplomat::rust_link(icu::time::TimeZoneInfo::with_zone_name_timestamp, FnInStruct)] #[diplomat::rust_link( icu::time::zone::ZoneNameTimestamp::from_zoned_date_time_iso, FnInStruct, compact )] #[diplomat::rust_link(icu::time::zone::ZoneNameTimestamp, Struct, compact)] pub fn at_timestamp(&self, timestamp: i64) -> Box { Box::new(Self { zone_name_timestamp: Some( icu_time::zone::ZoneNameTimestamp::from_zoned_date_time_iso( icu_time::ZonedDateTime::from_epoch_milliseconds_and_utc_offset( timestamp, icu_time::zone::UtcOffset::zero(), ), ), ), ..*self }) } #[diplomat::rust_link(icu::time::TimeZoneInfo::zone_name_timestamp, FnInStruct)] #[diplomat::rust_link( icu::time::zone::ZoneNameTimestamp::to_zoned_date_time_iso, FnInStruct, hidden )] #[diplomat::rust_link( icu::time::zone::ZoneNameTimestamp::to_date_time_iso, FnInStruct, hidden )] #[diplomat::attr(auto, getter)] /// Returns the DateTime for the UTC zone name reference time pub fn zone_name_date_time(&self) -> Option { let datetime = self.zone_name_timestamp?.to_zoned_date_time_iso(); Some(IsoDateTime { date: Box::new(IsoDate(datetime.date)), time: Box::new(Time(datetime.time)), }) } #[diplomat::rust_link(icu::time::TimeZoneInfo::with_variant, FnInStruct)] #[deprecated(note = "returns unmodified copy")] #[allow(deprecated)] pub fn with_variant(&self, _time_variant: TimeZoneVariant) -> Box { Box::new(*self) } #[diplomat::attr(auto, getter)] #[diplomat::rust_link(icu::time::TimeZoneInfo::offset, FnInStruct)] pub fn offset(&self) -> Option> { self.offset.map(UtcOffset).map(Box::new) } #[deprecated(note = "does nothing")] #[diplomat::rust_link(icu::time::TimeZoneInfo::infer_variant, FnInStruct)] #[diplomat::rust_link(icu::time::zone::TimeZoneVariant, Enum, compact)] #[allow(deprecated)] pub fn infer_variant( &mut self, _offset_calculator: &crate::unstable::variant_offset::ffi::VariantOffsetsCalculator, ) -> Option<()> { Some(()) } #[diplomat::rust_link(icu::time::TimeZoneInfo::variant, FnInStruct)] #[diplomat::attr(demo_gen, disable)] // this just returns a constructor argument #[deprecated(note = "always returns null")] #[allow(deprecated)] pub fn variant(&self) -> Option { None } } } impl From for TimeZoneInfo { fn from(other: icu_time::zone::UtcOffset) -> Self { Self { id: icu_time::TimeZone::UNKNOWN, offset: Some(other), zone_name_timestamp: None, } } } impl From> for TimeZoneInfo { fn from(other: icu_time::TimeZoneInfo) -> Self { Self { id: other.id(), offset: other.offset(), zone_name_timestamp: None, } } } impl From> for TimeZoneInfo { fn from(other: icu_time::TimeZoneInfo) -> Self { Self { id: other.id(), offset: other.offset(), zone_name_timestamp: Some(other.zone_name_timestamp()), } } } #[allow(deprecated)] impl From> for TimeZoneInfo { fn from(other: icu_time::TimeZoneInfo) -> Self { Self { id: other.id(), offset: other.offset(), zone_name_timestamp: Some(other.zone_name_timestamp()), } } }