1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
// 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 crate::date::*; use std::str::FromStr; // TODO(#622) link [`TimeZoneFormat`] appropriately once it is public. /// A temporary struct that implements [`TimeZoneInput`] /// and is used in tests, benchmarks and examples of this component. /// /// *Notice:* Rust at the moment does not have a canonical way to represent time zones. We are introducing /// [`MockTimeZone`] as an example of the data necessary for ICU `TimeZoneFormat` to work, and /// [we hope to work with the community](https://github.com/unicode-org/icu4x/blob/main/docs/research/datetime.md) /// to develop core date and time APIs that will work as an input for this component. /// /// # Examples /// /// ``` /// use icu::datetime::mock::time_zone::MockTimeZone; /// use icu::datetime::date::GmtOffset; /// /// let tz1 = MockTimeZone::new( /// GmtOffset::default(), /// /* time_zone_id */ None, /// /* metazone_id */ None, /// /* time_variaint */ None, /// ); /// /// let tz2: MockTimeZone = "+05:00".parse() /// .expect("Failed to parse a time zone."); /// ``` #[derive(Debug, Default)] pub struct MockTimeZone { /// The GMT offset in seconds. pub gmt_offset: GmtOffset, /// The IANA time-zone identifier // TODO(#606) change this to BCP-47 identifier pub time_zone_id: Option<String>, /// The CLDR metazone identifier // TODO(#528) change this to <TBD> identifier pub metazone_id: Option<String>, /// The time variant e.g. "daylight" or "standard" pub time_variant: Option<String>, } impl MockTimeZone { /// Creates a new [`MockTimeZone`]. /// A GMT offset is required, as it is used as a final fallback for formatting. /// The other arguments optionally allow access to more robust formats. pub const fn new( gmt_offset: GmtOffset, time_zone_id: Option<String>, metazone_id: Option<String>, time_variant: Option<String>, ) -> Self { Self { gmt_offset, time_zone_id, metazone_id, time_variant, } } } impl FromStr for MockTimeZone { type Err = DateTimeError; /// Parse a [`MockTimeZone`] from a string. /// /// This utility is for easily creating time zones, not a complete robust solution. /// /// The offset must range from GMT-12 to GMT+14. /// The string must be an ISO-8601 time zone designator: /// e.g. Z /// e.g. +05 /// e.g. +0500 /// e.g. +05:00 /// /// # Examples /// /// ``` /// use icu::datetime::mock::time_zone::MockTimeZone; /// /// let tz0: MockTimeZone = "Z".parse().expect("Failed to parse a time zone."); /// let tz1: MockTimeZone = "+02".parse().expect("Failed to parse a time zone."); /// let tz2: MockTimeZone = "-0230".parse().expect("Failed to parse a time zone."); /// let tz3: MockTimeZone = "+02:30".parse().expect("Failed to parse a time zone."); /// ``` fn from_str(input: &str) -> Result<Self, Self::Err> { let gmt_offset = GmtOffset::from_str(input)?; Ok(Self { gmt_offset, time_zone_id: None, metazone_id: None, time_variant: None, }) } } impl TimeZoneInput for MockTimeZone { fn gmt_offset(&self) -> GmtOffset { self.gmt_offset } fn time_zone_id(&self) -> Option<&str> { self.time_zone_id.as_ref().map(AsRef::as_ref) } fn metazone_id(&self) -> Option<&str> { self.metazone_id.as_ref().map(AsRef::as_ref) } fn time_variant(&self) -> Option<&str> { self.time_variant.as_ref().map(AsRef::as_ref) } }