1use ffi::TimeZoneInfo;
6
7#[diplomat::bridge]
8#[diplomat::abi_rename = "icu4x_{0}_mv1"]
9#[diplomat::attr(auto, namespace = "icu4x")]
10pub mod ffi {
11 use alloc::boxed::Box;
12
13 use crate::unstable::{
14 date::ffi::IsoDate,
15 datetime::ffi::IsoDateTime,
16 time::ffi::Time,
17 variant_offset::ffi::{UtcOffset, VariantOffsetsCalculator},
18 };
19
20 #[diplomat::opaque]
21 #[diplomat::rust_link(icu::time::TimeZone, Struct)]
22 pub struct TimeZone(pub(crate) icu_time::TimeZone);
23
24 impl TimeZone {
25 #[diplomat::rust_link(icu::time::TimeZoneInfo::unknown, FnInStruct)]
27 #[diplomat::rust_link(icu::time::TimeZone::unknown, FnInStruct, hidden)]
28 #[diplomat::attr(auto, named_constructor)]
29 pub fn unknown() -> Box<TimeZone> {
30 Box::new(TimeZone(icu_time::TimeZone::UNKNOWN))
31 }
32
33 #[diplomat::rust_link(icu::time::TimeZone::is_unknown, FnInStruct)]
35 pub fn is_unknown(&self) -> bool {
36 self.0.is_unknown()
37 }
38
39 #[diplomat::rust_link(icu::time::TimeZone, Struct, compact)]
43 #[diplomat::attr(auto, named_constructor = "from_bcp47")]
44 #[diplomat::demo(default_constructor)]
45 pub fn create_from_bcp47(id: &DiplomatStr) -> Box<Self> {
46 icu_locale_core::subtags::Subtag::try_from_utf8(id)
47 .map(icu_time::TimeZone)
48 .map(TimeZone)
49 .map(Box::new)
50 .unwrap_or(Self::unknown())
51 }
52
53 #[diplomat::rust_link(icu::time::TimeZone::with_offset, FnInStruct)]
54 pub fn with_offset(&self, offset: &UtcOffset) -> Box<TimeZoneInfo> {
55 Box::new(self.0.with_offset(Some(offset.0)).into())
56 }
57
58 #[diplomat::rust_link(icu::time::TimeZone::without_offset, FnInStruct)]
59 pub fn without_offset(&self) -> Box<TimeZoneInfo> {
60 Box::new(self.0.without_offset().into())
61 }
62 }
63
64 #[diplomat::enum_convert(icu_time::zone::TimeZoneVariant, needs_wildcard)]
65 pub enum TimeZoneVariant {
66 Standard,
67 Daylight,
68 }
69
70 impl TimeZoneVariant {
71 #[diplomat::rust_link(icu::time::zone::TimeZoneVariant::from_rearguard_isdst, FnInEnum)]
72 #[diplomat::rust_link(icu::time::TimeZoneInfo::with_variant, FnInStruct)]
73 #[diplomat::rust_link(icu::time::zone::TimeZoneVariant, Enum, compact)]
74 pub fn from_rearguard_isdst(isdst: bool) -> Self {
75 icu_time::zone::TimeZoneVariant::from_rearguard_isdst(isdst).into()
76 }
77 }
78
79 #[diplomat::opaque]
80 #[diplomat::rust_link(icu::time::TimeZoneInfo, Struct)]
81 #[diplomat::rust_link(icu::time::zone::models::AtTime, Struct, hidden)]
82 #[diplomat::rust_link(icu::time::zone::models::Base, Struct, hidden)]
83 #[diplomat::rust_link(icu::time::zone::models::Full, Struct, hidden)]
84 pub struct TimeZoneInfo {
85 pub(crate) id: icu_time::TimeZone,
86 pub(crate) offset: Option<icu_time::zone::UtcOffset>,
87 pub(crate) variant: Option<icu_time::zone::TimeZoneVariant>,
88 pub(crate) zone_name_timestamp: Option<icu_time::zone::ZoneNameTimestamp>,
89 }
90
91 impl TimeZoneInfo {
92 #[diplomat::rust_link(icu::time::TimeZoneInfo::utc, FnInStruct)]
94 #[diplomat::rust_link(icu::time::zone::UtcOffset::zero, FnInStruct, hidden)]
95 #[diplomat::attr(auto, named_constructor)]
96 pub fn utc() -> Box<TimeZoneInfo> {
97 Box::new(icu_time::TimeZoneInfo::utc().into())
98 }
99
100 #[diplomat::attr(auto, constructor)]
102 pub fn from_parts(
103 id: &TimeZone,
104 offset: Option<&UtcOffset>,
105 variant: Option<TimeZoneVariant>,
106 ) -> Box<TimeZoneInfo> {
107 Box::new(Self {
108 id: id.0,
109 offset: offset.map(|o| o.0),
110 variant: variant.map(Into::into),
111 zone_name_timestamp: None,
112 })
113 }
114
115 #[diplomat::rust_link(icu::time::TimeZoneInfo::id, FnInStruct)]
116 #[diplomat::attr(demo_gen, disable)] pub fn id(&self) -> Box<TimeZone> {
118 Box::new(TimeZone(self.id))
119 }
120
121 #[diplomat::rust_link(icu::time::TimeZoneInfo::at_date_time_iso, FnInStruct)]
130 #[diplomat::rust_link(icu::time::zone::ZoneNameTimestamp, Struct, compact)]
131 #[diplomat::rust_link(
132 icu::time::TimeZoneInfo::with_zone_name_timestamp,
133 FnInStruct,
134 hidden
135 )]
136 #[diplomat::rust_link(
137 icu::time::zone::ZoneNameTimestamp::from_date_time_iso,
138 FnInStruct,
139 hidden
140 )]
141 #[diplomat::rust_link(
142 icu::time::zone::ZoneNameTimestamp::far_in_future,
143 FnInStruct,
144 hidden
145 )] #[diplomat::rust_link(icu::time::zone::ZoneNameTimestamp::far_in_past, FnInStruct, hidden)] pub fn at_date_time_iso(&self, date: &IsoDate, time: &Time) -> Box<Self> {
148 Box::new(Self {
149 zone_name_timestamp: Some(icu_time::zone::ZoneNameTimestamp::from_date_time_iso(
150 icu_time::DateTime {
151 date: date.0,
152 time: time.0,
153 },
154 )),
155 ..*self
156 })
157 }
158
159 #[diplomat::rust_link(icu::time::TimeZoneInfo::zone_name_timestamp, FnInStruct)]
160 #[diplomat::rust_link(
161 icu::time::zone::ZoneNameTimestamp::to_date_time_iso,
162 FnInStruct,
163 hidden
164 )]
165 pub fn zone_name_date_time(&self) -> Option<IsoDateTime> {
166 let datetime = self.zone_name_timestamp?.to_date_time_iso();
167 Some(IsoDateTime {
168 date: Box::new(IsoDate(datetime.date)),
169 time: Box::new(Time(datetime.time)),
170 })
171 }
172
173 #[diplomat::rust_link(icu::time::TimeZoneInfo::with_variant, FnInStruct)]
174 pub fn with_variant(&self, time_variant: TimeZoneVariant) -> Box<Self> {
175 Box::new(Self {
176 variant: Some(time_variant.into()),
177 ..*self
178 })
179 }
180
181 #[diplomat::rust_link(icu::time::TimeZoneInfo::infer_variant, FnInStruct)]
185 #[diplomat::rust_link(icu::time::zone::TimeZoneVariant, Enum, compact)]
186 pub fn infer_variant(
187 &mut self,
188 offset_calculator: &VariantOffsetsCalculator,
189 ) -> Option<()> {
190 let info = self
191 .id
192 .with_offset(self.offset)
193 .with_zone_name_timestamp(self.zone_name_timestamp?)
194 .infer_variant(offset_calculator.0.as_borrowed());
195
196 self.id = info.id();
197 self.variant = Some(info.variant());
198 Some(())
199 }
200
201 #[diplomat::rust_link(icu::time::TimeZoneInfo::variant, FnInStruct)]
202 #[diplomat::attr(demo_gen, disable)] pub fn variant(&self) -> Option<TimeZoneVariant> {
204 self.variant.map(Into::into)
205 }
206 }
207}
208
209impl From<icu_time::zone::UtcOffset> for TimeZoneInfo {
210 fn from(other: icu_time::zone::UtcOffset) -> Self {
211 Self {
212 id: icu_time::TimeZone::UNKNOWN,
213 offset: Some(other),
214 variant: None,
215 zone_name_timestamp: None,
216 }
217 }
218}
219
220impl From<icu_time::TimeZoneInfo<icu_time::zone::models::Base>> for TimeZoneInfo {
221 fn from(other: icu_time::TimeZoneInfo<icu_time::zone::models::Base>) -> Self {
222 Self {
223 id: other.id(),
224 offset: other.offset(),
225 variant: None,
226 zone_name_timestamp: None,
227 }
228 }
229}
230
231impl From<icu_time::TimeZoneInfo<icu_time::zone::models::AtTime>> for TimeZoneInfo {
232 fn from(other: icu_time::TimeZoneInfo<icu_time::zone::models::AtTime>) -> Self {
233 Self {
234 id: other.id(),
235 offset: other.offset(),
236 variant: None,
237 zone_name_timestamp: Some(other.zone_name_timestamp()),
238 }
239 }
240}
241
242impl From<icu_time::TimeZoneInfo<icu_time::zone::models::Full>> for TimeZoneInfo {
243 fn from(other: icu_time::TimeZoneInfo<icu_time::zone::models::Full>) -> Self {
244 Self {
245 id: other.id(),
246 offset: other.offset(),
247 variant: Some(other.variant()),
248 zone_name_timestamp: Some(other.zone_name_timestamp()),
249 }
250 }
251}