-
Notifications
You must be signed in to change notification settings - Fork 182
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add IANA/BCP47 time zone name mappings #3499
Closed
Closed
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
1ae7862
Add boilerplate for NormalizedTimeZoneIdStr
sffc 5dc8c6d
Add data structs based on properties name structs
sffc 5341e17
fmt
sffc 85df3f9
Add IanaToBcp47MapV1Marker to datagen
sffc 2fc7d31
Add Bcp47ToIanaMapV1Marker to datagen
sffc 1e49656
fmt
sffc 062a52b
Add IanaToBcp47Mapper
sffc e0964a7
Add Bcp47ToIanaMapper
sffc f3d5859
Use IanaToBcp47Mapper in docs tests
sffc dceaa5b
Add FFI for the new Rust functions
sffc 744d2d5
Add C++ test
sffc a58a33a
Generate-readmes
sffc ad9e056
Fix icu_capi cargo-all-features
sffc File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
// 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::error::TimeZoneError; | ||
use crate::provider::names::*; | ||
use crate::TimeZoneBcp47Id; | ||
use icu_provider::prelude::*; | ||
|
||
/// A mapper from IANA time zone identifiers to BCP-47 time zone identifiers. | ||
/// | ||
/// # Examples | ||
/// | ||
/// Demonstration of usage with strict and loose lookup: | ||
/// | ||
/// ``` | ||
/// use icu::timezone::IanaToBcp47Mapper; | ||
/// | ||
/// let mapper = IanaToBcp47Mapper::try_new_unstable(&icu_testdata::unstable()).unwrap(); | ||
/// | ||
/// // Strict: the IANA identifier is already in case-canonical form, and we find a match | ||
/// let bcp47_id = mapper.as_borrowed().get_strict("America/Chicago"); | ||
/// assert_eq!(bcp47_id, Some("uschi".parse().unwrap())); | ||
/// | ||
/// // Strict: the IANA identifier is not in the correct case, so we find no match | ||
/// let bcp47_id = mapper.as_borrowed().get_strict("america/chicago"); | ||
/// assert_eq!(bcp47_id, None); | ||
/// | ||
/// // Loose: we find the IANA identifier even though it is in the wrong case | ||
/// let bcp47_id = mapper.as_borrowed().get_loose("america/chicago"); | ||
/// assert_eq!(bcp47_id, Some("uschi".parse().unwrap())); | ||
/// ``` | ||
#[derive(Debug)] | ||
pub struct IanaToBcp47Mapper { | ||
data: DataPayload<IanaToBcp47MapV1Marker>, | ||
} | ||
|
||
impl IanaToBcp47Mapper { | ||
/// Creates a new [`IanaToBcp47Mapper`]. | ||
/// | ||
/// See [`IanaToBcp47Mapper`] for an example. | ||
/// | ||
/// [📚 Help choosing a constructor](crate::constructors) | ||
/// <div class="stab unstable"> | ||
/// ⚠️ The bounds on this function may change over time, including in SemVer minor releases. | ||
/// </div> | ||
pub fn try_new_unstable<P>(provider: &P) -> Result<Self, TimeZoneError> | ||
where | ||
P: DataProvider<IanaToBcp47MapV1Marker> + ?Sized, | ||
{ | ||
let data = provider.load(Default::default())?.take_payload()?; | ||
Ok(Self { data }) | ||
} | ||
|
||
icu_provider::gen_any_buffer_constructors!(locale: skip, options: skip, error: TimeZoneError); | ||
|
||
/// Returns a borrowed version of the mapper that can be queried. | ||
/// | ||
/// This avoids a small potential cost of reading the data pointer. | ||
pub fn as_borrowed(&self) -> IanaToBcp47MapperBorrowed { | ||
IanaToBcp47MapperBorrowed { | ||
data: self.data.get(), | ||
} | ||
} | ||
} | ||
|
||
/// A borrowed wrapper around IANA-to-BCP47 time zone data, returned by | ||
/// [`IanaToBcp47Mapper::as_borrowed()`]. More efficient to query. | ||
#[derive(Debug)] | ||
pub struct IanaToBcp47MapperBorrowed<'a> { | ||
data: &'a IanaToBcp47MapV1<'a>, | ||
} | ||
|
||
impl<'a> IanaToBcp47MapperBorrowed<'a> { | ||
/// Looks up a BCP-47 time zone identifier based on an exact match for the given IANA | ||
/// time zone identifier. | ||
/// | ||
/// See examples in [`IanaToBcp47Mapper`]. | ||
pub fn get_strict(&self, iana_id: &str) -> Option<TimeZoneBcp47Id> { | ||
self.data | ||
.map | ||
.get_copied(NormalizedTimeZoneIdStr::from_str(iana_id)) | ||
} | ||
|
||
/// Looks up a BCP-47 time zone identifier based on an ASCII-case-insensitive match for | ||
/// the given IANA time zone identifier. | ||
/// | ||
/// This is the type of match specified in [ECMAScript Temporal]. | ||
/// | ||
/// See examples in [`IanaToBcp47Mapper`]. | ||
/// | ||
/// [ECMAScript Temporal]: https://tc39.es/proposal-temporal/#sec-isavailabletimezonename | ||
pub fn get_loose(&self, iana_id: &str) -> Option<TimeZoneBcp47Id> { | ||
self.data | ||
.map | ||
.get_copied_by(|probe| probe.cmp_loose(NormalizedTimeZoneIdStr::from_str(iana_id))) | ||
} | ||
} | ||
|
||
/// A mapper from BCP-47 time zone identifiers to canonical IANA time zone identifiers. | ||
/// | ||
/// This is mainly useful if the IANA identifier needs to be recovered. However, the ID returned | ||
/// from this function might not be the same as the one sourced from [`IanaToBcp47Mapper`]. | ||
/// | ||
/// # Examples | ||
/// | ||
/// Demonstration of canonicalization of the time zone identifier: | ||
/// | ||
/// ``` | ||
/// use icu::timezone::IanaToBcp47Mapper; | ||
/// use icu::timezone::Bcp47ToIanaMapper; | ||
/// | ||
/// let mapper1 = IanaToBcp47Mapper::try_new_unstable(&icu_testdata::unstable()).unwrap(); | ||
/// let mapper2 = Bcp47ToIanaMapper::try_new_unstable(&icu_testdata::unstable()).unwrap(); | ||
/// | ||
/// // Look up the time zone ID for "Asia/Calcutta" | ||
/// let bcp47_id = mapper1.as_borrowed().get_loose("asia/calcutta"); | ||
/// assert_eq!(bcp47_id, Some("inccu".parse().unwrap())); | ||
/// | ||
/// // Get it back as the canonical form "Asia/Kolkata" | ||
/// let mapper2_borrowed = mapper2.as_borrowed(); | ||
/// let iana_id = mapper2_borrowed.get(bcp47_id.unwrap()); | ||
/// assert_eq!(iana_id, Some("Asia/Kolkata")) | ||
/// ``` | ||
#[derive(Debug)] | ||
pub struct Bcp47ToIanaMapper { | ||
data: DataPayload<Bcp47ToIanaMapV1Marker>, | ||
} | ||
|
||
impl Bcp47ToIanaMapper { | ||
/// Creates a new [`Bcp47ToIanaMapper`]. | ||
/// | ||
/// See [`Bcp47ToIanaMapper`] for an example. | ||
/// | ||
/// [📚 Help choosing a constructor](crate::constructors) | ||
/// <div class="stab unstable"> | ||
/// ⚠️ The bounds on this function may change over time, including in SemVer minor releases. | ||
/// </div> | ||
pub fn try_new_unstable<P>(provider: &P) -> Result<Self, TimeZoneError> | ||
where | ||
P: DataProvider<Bcp47ToIanaMapV1Marker> + ?Sized, | ||
{ | ||
let data = provider.load(Default::default())?.take_payload()?; | ||
Ok(Self { data }) | ||
} | ||
|
||
icu_provider::gen_any_buffer_constructors!(locale: skip, options: skip, error: TimeZoneError); | ||
|
||
/// Returns a borrowed version of the mapper that can be queried. | ||
/// | ||
/// This avoids a small potential cost of reading the data pointer. | ||
pub fn as_borrowed(&self) -> Bcp47ToIanaMapperBorrowed { | ||
Bcp47ToIanaMapperBorrowed { | ||
data: self.data.get(), | ||
} | ||
} | ||
} | ||
|
||
/// A borrowed wrapper around IANA-to-BCP47 time zone data, returned by | ||
/// [`Bcp47ToIanaMapper::as_borrowed()`]. More efficient to query. | ||
#[derive(Debug)] | ||
pub struct Bcp47ToIanaMapperBorrowed<'a> { | ||
data: &'a Bcp47ToIanaMapV1<'a>, | ||
} | ||
|
||
impl<'a> Bcp47ToIanaMapperBorrowed<'a> { | ||
/// Looks up a BCP-47 time zone identifier based on an exact match for the given IANA | ||
/// time zone identifier. | ||
/// | ||
/// See examples in [`Bcp47ToIanaMapper`]. | ||
pub fn get(&self, bcp47_id: TimeZoneBcp47Id) -> Option<&str> { | ||
self.data.map.get(&bcp47_id.0.to_unvalidated()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue: not sure if we can say this fixes #2909 since this is just the data model, there's no fetcher struct yet
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just pushed the API