Skip to content
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

Components bag support with only skeleton matching #587

Merged
merged 9 commits into from
Apr 8, 2021
3 changes: 3 additions & 0 deletions components/datetime/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).

use crate::pattern;
use crate::skeleton::SkeletonError;
use icu_provider::prelude::DataError;

/// A list of possible error outcomes for the [`DateTimeFormat`](crate::DateTimeFormat) struct.
Expand All @@ -18,6 +19,8 @@ pub enum DateTimeFormatError {
/// Missing field in date time input
/// TODO: How can we return which field was missing?
MissingInputField,
/// An error from skeleton matching,
Skeleton(SkeletonError),
}

impl From<DataError> for DateTimeFormatError {
Expand Down
15 changes: 15 additions & 0 deletions components/datetime/src/fields/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,21 @@ pub struct Field {
pub length: FieldLength,
}

impl Field {
pub fn get_length_type(&self) -> TextOrNumeric {
match self.symbol {
FieldSymbol::Year(year) => year.get_length_type(&self.length),
FieldSymbol::Month(month) => month.get_length_type(&self.length),
FieldSymbol::Day(day) => day.get_length_type(&self.length),
FieldSymbol::Weekday(weekday) => weekday.get_length_type(&self.length),
FieldSymbol::DayPeriod(day_period) => day_period.get_length_type(&self.length),
FieldSymbol::Hour(hour) => hour.get_length_type(&self.length),
FieldSymbol::Minute => TextOrNumeric::Numeric,
FieldSymbol::Second(second) => second.get_length_type(&self.length),
}
}
}

impl From<(FieldSymbol, FieldLength)> for Field {
fn from(input: (FieldSymbol, FieldLength)) -> Self {
Self {
Expand Down
68 changes: 68 additions & 0 deletions components/datetime/src/fields/symbols.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).

use crate::fields::FieldLength;
use std::{cmp::Ordering, convert::TryFrom};

#[derive(Debug, PartialEq)]
Expand All @@ -28,6 +29,18 @@ pub enum FieldSymbol {
Second(Second),
}

#[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub enum TextOrNumeric {
Text,
Numeric,
}

/// FieldSymbols can be either text or numeric. This categorization is important when matching
/// skeletons with a components::Bag.
pub trait LengthType {
fn get_length_type(&self, length: &FieldLength) -> TextOrNumeric;
}

impl FieldSymbol {
/// Skeletons are a Vec<Field>, and represent the Fields that can be used to match to a
/// specific pattern. The order of the Vec does not affect the Pattern that is output.
Expand Down Expand Up @@ -158,6 +171,12 @@ pub enum Year {
WeekOf,
}

impl LengthType for Year {
fn get_length_type(&self, _length: &FieldLength) -> TextOrNumeric {
TextOrNumeric::Numeric
}
}

impl TryFrom<u8> for Year {
type Error = SymbolError;
fn try_from(b: u8) -> Result<Self, Self::Error> {
Expand Down Expand Up @@ -185,6 +204,19 @@ pub enum Month {
StandAlone,
}

impl LengthType for Month {
fn get_length_type(&self, length: &FieldLength) -> TextOrNumeric {
match length {
FieldLength::One => TextOrNumeric::Numeric,
FieldLength::TwoDigit => TextOrNumeric::Numeric,
FieldLength::Abbreviated => TextOrNumeric::Text,
FieldLength::Wide => TextOrNumeric::Text,
FieldLength::Narrow => TextOrNumeric::Text,
FieldLength::Six => TextOrNumeric::Text,
}
}
}

impl TryFrom<u8> for Month {
type Error = SymbolError;
fn try_from(b: u8) -> Result<Self, Self::Error> {
Expand Down Expand Up @@ -214,6 +246,12 @@ pub enum Day {
ModifiedJulianDay,
}

impl LengthType for Day {
fn get_length_type(&self, _length: &FieldLength) -> TextOrNumeric {
TextOrNumeric::Numeric
}
}

impl TryFrom<u8> for Day {
type Error = SymbolError;
fn try_from(b: u8) -> Result<Self, Self::Error> {
Expand Down Expand Up @@ -245,6 +283,12 @@ pub enum Hour {
H24,
}

impl LengthType for Hour {
fn get_length_type(&self, _length: &FieldLength) -> TextOrNumeric {
TextOrNumeric::Numeric
}
}

impl TryFrom<u8> for Hour {
type Error = SymbolError;
fn try_from(b: u8) -> Result<Self, Self::Error> {
Expand Down Expand Up @@ -275,6 +319,12 @@ pub enum Second {
Millisecond,
}

impl LengthType for Second {
fn get_length_type(&self, _length: &FieldLength) -> TextOrNumeric {
TextOrNumeric::Numeric
}
}

impl TryFrom<u8> for Second {
type Error = SymbolError;
fn try_from(b: u8) -> Result<Self, Self::Error> {
Expand Down Expand Up @@ -304,6 +354,18 @@ pub enum Weekday {
StandAlone,
}

impl LengthType for Weekday {
fn get_length_type(&self, length: &FieldLength) -> TextOrNumeric {
match self {
Weekday::Format => TextOrNumeric::Text,
Weekday::Local | Weekday::StandAlone => match length {
FieldLength::One | FieldLength::TwoDigit => TextOrNumeric::Text,
_ => TextOrNumeric::Numeric,
},
}
}
}

impl TryFrom<u8> for Weekday {
type Error = SymbolError;
fn try_from(b: u8) -> Result<Self, Self::Error> {
Expand Down Expand Up @@ -332,6 +394,12 @@ pub enum DayPeriod {
NoonMidnight,
}

impl LengthType for DayPeriod {
fn get_length_type(&self, _length: &FieldLength) -> TextOrNumeric {
TextOrNumeric::Text
}
}

impl TryFrom<u8> for DayPeriod {
type Error = SymbolError;
fn try_from(b: u8) -> Result<Self, Self::Error> {
Expand Down
Loading