tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

timezone.rs (9381B)


      1 // This file is part of ICU4X. For terms of use, please see the file
      2 // called LICENSE at the top level of the ICU4X source tree
      3 // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
      4 
      5 use ffi::TimeZoneInfo;
      6 
      7 #[diplomat::bridge]
      8 #[diplomat::abi_rename = "icu4x_{0}_mv1"]
      9 #[diplomat::attr(auto, namespace = "icu4x")]
     10 pub 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        /// The unknown time zone.
     26        #[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        /// Whether the time zone is the unknown zone.
     34        #[diplomat::rust_link(icu::time::TimeZone::is_unknown, FnInStruct)]
     35        pub fn is_unknown(&self) -> bool {
     36            self.0.is_unknown()
     37        }
     38 
     39        /// Creates a time zone from a BCP-47 string.
     40        ///
     41        /// Returns the unknown time zone if the string is not a valid BCP-47 subtag.
     42        #[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        /// Sets the `variant` field to "daylight" time.
     72        #[diplomat::rust_link(icu::time::zone::TimeZoneVariant::from_rearguard_isdst, FnInEnum)]
     73        #[diplomat::rust_link(icu::time::TimeZoneInfo::with_variant, FnInStruct)]
     74        #[diplomat::rust_link(icu::time::zone::TimeZoneVariant, Enum, compact)]
     75        pub fn from_rearguard_isdst(&mut self, isdst: bool) -> Self {
     76            icu_time::zone::TimeZoneVariant::from_rearguard_isdst(isdst).into()
     77        }
     78    }
     79 
     80    #[diplomat::opaque]
     81    #[diplomat::rust_link(icu::time::TimeZoneInfo, Struct)]
     82    #[diplomat::rust_link(icu::time::zone::models::AtTime, Struct, hidden)]
     83    #[diplomat::rust_link(icu::time::zone::models::Base, Struct, hidden)]
     84    #[diplomat::rust_link(icu::time::zone::models::Full, Struct, hidden)]
     85    pub struct TimeZoneInfo {
     86        pub(crate) id: icu_time::TimeZone,
     87        pub(crate) offset: Option<icu_time::zone::UtcOffset>,
     88        pub(crate) variant: Option<icu_time::zone::TimeZoneVariant>,
     89        pub(crate) zone_name_timestamp: Option<icu_time::zone::ZoneNameTimestamp>,
     90    }
     91 
     92    impl TimeZoneInfo {
     93        /// Creates a time zone for UTC (Coordinated Universal Time).
     94        #[diplomat::rust_link(icu::time::TimeZoneInfo::utc, FnInStruct)]
     95        #[diplomat::rust_link(icu::time::zone::UtcOffset::zero, FnInStruct, hidden)]
     96        #[diplomat::attr(auto, named_constructor)]
     97        pub fn utc() -> Box<TimeZoneInfo> {
     98            Box::new(icu_time::TimeZoneInfo::utc().into())
     99        }
    100 
    101        /// Creates a time zone info from parts.
    102        #[diplomat::attr(auto, constructor)]
    103        pub fn from_parts(
    104            id: &TimeZone,
    105            offset: Option<&UtcOffset>,
    106            variant: Option<TimeZoneVariant>,
    107        ) -> Box<TimeZoneInfo> {
    108            Box::new(Self {
    109                id: id.0,
    110                offset: offset.map(|o| o.0),
    111                variant: variant.map(Into::into),
    112                zone_name_timestamp: None,
    113            })
    114        }
    115 
    116        #[diplomat::rust_link(icu::time::TimeZoneInfo::id, FnInStruct)]
    117        pub fn id(&self) -> Box<TimeZone> {
    118            Box::new(TimeZone(self.id))
    119        }
    120 
    121        /// Sets the datetime at which to interpret the time zone
    122        /// for display name lookup.
    123        ///
    124        /// Notes:
    125        ///
    126        /// - If not set, the formatting datetime is used if possible.
    127        /// - The constraints are the same as with `ZoneNameTimestamp` in Rust.
    128        /// - Set to year 1000 or 9999 for a reference far in the past or future.
    129        #[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        )] // documented
    146        #[diplomat::rust_link(icu::time::zone::ZoneNameTimestamp::far_in_past, FnInStruct, hidden)] // documented
    147        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        /// Infers the zone variant.
    182        ///
    183        /// Requires the offset and local time to be set.
    184        #[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        pub fn variant(&self) -> Option<TimeZoneVariant> {
    203            self.variant.map(Into::into)
    204        }
    205    }
    206 }
    207 
    208 impl From<icu_time::zone::UtcOffset> for TimeZoneInfo {
    209    fn from(other: icu_time::zone::UtcOffset) -> Self {
    210        Self {
    211            id: icu_time::TimeZone::UNKNOWN,
    212            offset: Some(other),
    213            variant: None,
    214            zone_name_timestamp: None,
    215        }
    216    }
    217 }
    218 
    219 impl From<icu_time::TimeZoneInfo<icu_time::zone::models::Base>> for TimeZoneInfo {
    220    fn from(other: icu_time::TimeZoneInfo<icu_time::zone::models::Base>) -> Self {
    221        Self {
    222            id: other.id(),
    223            offset: other.offset(),
    224            variant: None,
    225            zone_name_timestamp: None,
    226        }
    227    }
    228 }
    229 
    230 impl From<icu_time::TimeZoneInfo<icu_time::zone::models::AtTime>> for TimeZoneInfo {
    231    fn from(other: icu_time::TimeZoneInfo<icu_time::zone::models::AtTime>) -> Self {
    232        Self {
    233            id: other.id(),
    234            offset: other.offset(),
    235            variant: None,
    236            zone_name_timestamp: Some(other.zone_name_timestamp()),
    237        }
    238    }
    239 }
    240 
    241 impl From<icu_time::TimeZoneInfo<icu_time::zone::models::Full>> for TimeZoneInfo {
    242    fn from(other: icu_time::TimeZoneInfo<icu_time::zone::models::Full>) -> Self {
    243        Self {
    244            id: other.id(),
    245            offset: other.offset(),
    246            variant: Some(other.variant()),
    247            zone_name_timestamp: Some(other.zone_name_timestamp()),
    248        }
    249    }
    250 }