Skip to content

Commit

Permalink
Checkpoint: treat time zones more like other field sets
Browse files Browse the repository at this point in the history
  • Loading branch information
sffc committed Nov 11, 2024
1 parent dc64d9b commit 76a48e8
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 58 deletions.
55 changes: 53 additions & 2 deletions components/datetime/src/dynamic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::neo_serde::*;
use crate::neo_skeleton::NeoTimeZoneStyle;
use crate::options::preferences::HourCycle;
use crate::raw::neo::RawNeoOptions;
use crate::{fieldset, NeoSkeletonLength};
use crate::{fields, fieldset, NeoSkeletonLength};
use icu_provider::prelude::*;

/// An enumeration over all possible date field sets.
Expand Down Expand Up @@ -65,6 +65,17 @@ pub enum TimeFieldSet {
T(fieldset::T),
}

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum ZoneFieldSet {
Z(fieldset::Z),
// Zs(fieldset::Zs),
O(fieldset::O),
V(fieldset::V),
// Vs(fieldset::Vs),
L(fieldset::L),
}

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub struct TimeZoneStyleWithLength {
Expand Down Expand Up @@ -167,7 +178,7 @@ pub enum CompositeFieldSet {
/// Field set for a time.
Time(TimeFieldSet),
/// Field set for a time zone.
Zone(TimeZoneStyleWithLength),
Zone(ZoneFieldSet),
/// Field set for a date and a time together.
DateTime(DateAndTimeFieldSet),
/// Field set for a date and a time zone together.
Expand Down Expand Up @@ -221,6 +232,18 @@ macro_rules! impl_attrs {
}
}
};
(@zone_fns, $type:path, [$($variant:ident),+,]) => {
impl_attrs! { @to_raw_options, $type, [$($variant),+,] }
impl $type {
pub(crate) fn to_field(self) -> (fields::TimeZone, fields::FieldLength) {
match self {
$(
Self::$variant(variant) => variant.to_field(),
)+
}
}
}
};
(@datetime_fns, $type:path, [$(($d_variant:ident, $variant:ident)),+,]) => {
impl_attrs! { @to_raw_options, $type, [$($variant),+,] }
impl $type {
Expand Down Expand Up @@ -336,6 +359,34 @@ impl TimeZoneStyleWithLength {
}
}

impl_attrs! {
@zone_fns,
ZoneFieldSet,
[
Z,
// Zs,
O,
V,
// Vs,
L,
]
}

impl ZoneFieldSet {
pub(crate) fn from_time_zone_style_and_length(
style: NeoTimeZoneStyle,
length: NeoSkeletonLength,
) -> Self {
match style {
NeoTimeZoneStyle::Default => Self::L(fieldset::L::with_length(length)),
NeoTimeZoneStyle::Location => Self::Z(fieldset::Z::with_length(length)),
NeoTimeZoneStyle::Generic => Self::V(fieldset::V::with_length(length)),
NeoTimeZoneStyle::Specific => Self::Z(fieldset::Z::with_length(length)),
NeoTimeZoneStyle::Offset => Self::O(fieldset::O::with_length(length)),
}
}
}

impl_attrs! {
@attrs,
DateAndTimeFieldSet,
Expand Down
47 changes: 39 additions & 8 deletions components/datetime/src/fieldset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pub use crate::combo::Combo;

use crate::{
dynamic::*,
fields,
format::neo::*,
neo_skeleton::*,
provider::{neo::*, time_zones::tz, *},
Expand Down Expand Up @@ -689,6 +690,10 @@ macro_rules! impl_zone_marker {
sample_length = $sample_length:ident,
// A sample string. A docs test will be generated!
sample = $sample:literal,
// The field symbol and field length when the semantic length is short/medium.
field_short = $field_short:expr,
// The field symbol and field length when the semantic length is long.
field_long = $field_long:expr,
// Whether zone-essentials should be loaded.
$(zone_essentials = $zone_essentials_yes:ident,)?
// Whether locations formats can occur.
Expand All @@ -709,6 +714,8 @@ macro_rules! impl_zone_marker {
$(input_variant = $variant_input_yes:ident,)?
// Whether to require the Local Time
$(input_localtime = $localtime_input_yes:ident,)?
// Whether this time zone style is enumerated in ZoneFieldSet
$(enumerated = $enumerated_yes:ident,)?
) => {
impl_marker_with_options!(
#[doc = concat!("**“", $sample, "**” ⇒ ", $description)]
Expand Down Expand Up @@ -814,15 +821,23 @@ macro_rules! impl_zone_marker {
type TimePrecisionOption = datetime_marker_helper!(@option/timeprecision,);
type GluePatternV1Marker = datetime_marker_helper!(@glue,);
}
impl GetField<CompositeFieldSet> for $type {
#[inline]
fn get_field(&self) -> CompositeFieldSet {
CompositeFieldSet::Zone(TimeZoneStyleWithLength {
style: $components,
length: self.length,
})
$(
const _: () = yes_to!((), $enumerated_yes); // condition for this macro block
impl GetField<CompositeFieldSet> for $type {
#[inline]
fn get_field(&self) -> CompositeFieldSet {
CompositeFieldSet::Zone(ZoneFieldSet::$type(*self))
}
}
}
impl $type {
pub(crate) fn to_field(self) -> (fields::TimeZone, fields::FieldLength) {
match self.length {
NeoSkeletonLength::Short | NeoSkeletonLength::Medium => $field_short,
NeoSkeletonLength::Long => $field_long,
}
}
}
)?
};
}

Expand Down Expand Up @@ -1131,6 +1146,8 @@ impl_zone_marker!(
description = "time zone in specific non-location format",
sample_length = long,
sample = "Central Daylight Time",
field_short = (fields::TimeZone::SpecificNonLocation, fields::FieldLength::One),
field_long = (fields::TimeZone::SpecificNonLocation, fields::FieldLength::Four),
zone_essentials = yes,
zone_locations = yes,
zone_specific_long = yes,
Expand All @@ -1139,6 +1156,7 @@ impl_zone_marker!(
input_tzid = yes,
input_variant = yes,
input_localtime = yes,
enumerated = yes,
);

impl_zone_marker!(
Expand Down Expand Up @@ -1226,6 +1244,8 @@ impl_zone_marker!(
description = "time zone in specific non-location format (only short)",
sample_length = short,
sample = "CDT",
field_short = (fields::TimeZone::SpecificNonLocation, fields::FieldLength::One),
field_long = (fields::TimeZone::SpecificNonLocation, fields::FieldLength::One),
zone_essentials = yes,
zone_specific_short = yes,
metazone_periods = yes,
Expand Down Expand Up @@ -1286,7 +1306,10 @@ impl_zone_marker!(
description = "UTC offset",
sample_length = medium,
sample = "GMT-5",
field_short = (fields::TimeZone::LocalizedOffset, fields::FieldLength::One),
field_long = (fields::TimeZone::LocalizedOffset, fields::FieldLength::Four),
zone_essentials = yes,
enumerated = yes,
);

impl_zone_marker!(
Expand Down Expand Up @@ -1348,13 +1371,16 @@ impl_zone_marker!(
description = "time zone in generic non-location format",
sample_length = long,
sample = "Central Time",
field_short = (fields::TimeZone::GenericNonLocation, fields::FieldLength::One),
field_long = (fields::TimeZone::GenericNonLocation, fields::FieldLength::Four),
zone_essentials = yes,
zone_locations = yes,
zone_generic_long = yes,
zone_generic_short = yes,
metazone_periods = yes,
input_tzid = yes,
input_localtime = yes,
enumerated = yes,
);

impl_zone_marker!(
Expand Down Expand Up @@ -1439,6 +1465,8 @@ impl_zone_marker!(
description = "time zone in generic non-location format (only short)",
sample_length = short,
sample = "CT",
field_short = (fields::TimeZone::GenericNonLocation, fields::FieldLength::One),
field_long = (fields::TimeZone::GenericNonLocation, fields::FieldLength::One),
zone_essentials = yes,
zone_locations = yes,
zone_generic_short = yes,
Expand Down Expand Up @@ -1477,9 +1505,12 @@ impl_zone_marker!(
description = "time zone in location format",
sample_length = long,
sample = "Chicago Time",
field_short = (fields::TimeZone::Location, fields::FieldLength::Four),
field_long = (fields::TimeZone::Location, fields::FieldLength::Four),
zone_essentials = yes,
zone_locations = yes,
input_tzid = yes,
enumerated = yes,
);

impl_zoneddatetime_marker!(
Expand Down
52 changes: 35 additions & 17 deletions components/datetime/src/neo_serde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,7 @@ impl From<CompositeFieldSet> for SemanticSkeletonSerde {
}
CompositeFieldSet::Time(v) => FieldSetSerde::from_time_field_set(v),
CompositeFieldSet::Zone(v) => {
let zone_serde = FieldSetSerde::from_time_zone_style(v.style);
(
zone_serde,
RawNeoOptions {
length: v.length,
alignment: None,
year_style: None,
time_precision: None,
},
)
FieldSetSerde::from_zone_field_set(v)
}
CompositeFieldSet::DateTime(v) => {
let (date_serde, date_options) =
Expand Down Expand Up @@ -119,14 +110,17 @@ impl TryFrom<SemanticSkeletonSerde> for CompositeFieldSet {
.map(CompositeFieldSet::Time)
.ok_or(Error::InvalidFields),
(false, false, true) => zone
.to_time_zone_style()
.map(|style| {
CompositeFieldSet::Zone(TimeZoneStyleWithLength {
style,
length: options.length,
})
})
.to_zone_field_set(options)
.map(CompositeFieldSet::Zone)
.ok_or(Error::InvalidFields),
// .to_time_zone_style()
// .map(|style| {
// CompositeFieldSet::Zone(TimeZoneStyleWithLength {
// style,
// length: options.length,
// })
// })
// .ok_or(Error::InvalidFields),
(true, true, false) => date
.to_date_field_set(options)
.map(|date_field_set| {
Expand Down Expand Up @@ -494,6 +488,30 @@ impl FieldSetSerde {
_ => None,
}
}

fn from_zone_field_set(value: ZoneFieldSet) -> (Self, RawNeoOptions) {
match value {
ZoneFieldSet::Z(v) => (Self::ZONE_SPECIFIC, v.to_raw_options()),
// ZoneFieldSet::Zs(v) => (Self::ZONE_SPECIFIC, v.to_raw_options()),
ZoneFieldSet::O(v) => (Self::ZONE_OFFSET, v.to_raw_options()),
ZoneFieldSet::V(v) => (Self::ZONE_GENERIC, v.to_raw_options()),
// ZoneFieldSet::Vs(v) => (Self::ZONE_GENERIC, v.to_raw_options()),
ZoneFieldSet::L(v) => (Self::ZONE_LOCATION, v.to_raw_options()),
}
}

fn to_zone_field_set(self, options: RawNeoOptions) -> Option<ZoneFieldSet> {
use ZoneFieldSet::*;
match self {
Self::ZONE_SPECIFIC => Some(Z(fieldset::Z::from_raw_options(options))),
// Self::ZONE_SPECIFIC => Some(Zs(fieldset::Zs::from_raw_options(options))),
Self::ZONE_OFFSET => Some(O(fieldset::O::from_raw_options(options))),
Self::ZONE_GENERIC => Some(V(fieldset::V::from_raw_options(options))),
// Self::ZONE_GENERIC => Some(Vs(fieldset::Vs::from_raw_options(options))),
Self::ZONE_LOCATION => Some(L(fieldset::L::from_raw_options(options))),
_ => None,
}
}
}

#[test]
Expand Down
43 changes: 22 additions & 21 deletions components/datetime/src/raw/neo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +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::dynamic::{CompositeFieldSet, TimeFieldSet};
use crate::dynamic::{CompositeFieldSet, TimeFieldSet, ZoneFieldSet};
use crate::fields::{self, Field, FieldLength, FieldSymbol, TimeZone};
use crate::input::ExtractedInput;
use crate::neo_pattern::DateTimePattern;
Expand Down Expand Up @@ -441,17 +441,8 @@ impl<'a> TimePatternDataBorrowed<'a> {
}

impl ZonePatternSelectionData {
pub(crate) fn new_with_skeleton(
style: NeoTimeZoneStyle,
options: RawNeoOptions,
is_only_field: bool,
) -> Self {
let length = if is_only_field {
options.length
} else {
NeoSkeletonLength::Short
};
let (symbol, length) = style.resolve(length);
pub(crate) fn new_with_skeleton(field_set: ZoneFieldSet) -> Self {
let (symbol, length) = field_set.to_field();
let pattern_item = PatternItem::Field(Field {
symbol: FieldSymbol::TimeZone(symbol),
length,
Expand Down Expand Up @@ -530,9 +521,7 @@ impl DateTimeZonePatternSelectionData {
Ok(Self::Time(selection))
}
CompositeFieldSet::Zone(field_set) => {
let options = field_set.to_raw_options();
let selection =
ZonePatternSelectionData::new_with_skeleton(field_set.style, options, true);
let selection = ZonePatternSelectionData::new_with_skeleton(field_set);
Ok(Self::Zone(selection))
}
CompositeFieldSet::DateTime(field_set) => {
Expand Down Expand Up @@ -577,8 +566,12 @@ impl DateTimeZonePatternSelectionData {
field_set.id_str(),
options,
)?;
let zone =
ZonePatternSelectionData::new_with_skeleton(time_zone_style, options, false);
// Always use the short length for time zones when mixed with another field (Date)
let zone_field_set = ZoneFieldSet::from_time_zone_style_and_length(
time_zone_style,
NeoSkeletonLength::Short,
);
let zone = ZonePatternSelectionData::new_with_skeleton(zone_field_set);
let glue = Self::load_glue(glue_provider, locale, options, GlueType::DateZone)?;
Ok(Self::DateZoneGlue { date, zone, glue })
}
Expand All @@ -591,8 +584,12 @@ impl DateTimeZonePatternSelectionData {
options,
prefs,
)?;
let zone =
ZonePatternSelectionData::new_with_skeleton(time_zone_style, options, false);
// Always use the short length for time zones when mixed with another field (Time)
let zone_field_set = ZoneFieldSet::from_time_zone_style_and_length(
time_zone_style,
NeoSkeletonLength::Short,
);
let zone = ZonePatternSelectionData::new_with_skeleton(zone_field_set);
let glue = Self::load_glue(glue_provider, locale, options, GlueType::TimeZone)?;
Ok(Self::TimeZoneGlue { time, zone, glue })
}
Expand All @@ -611,8 +608,12 @@ impl DateTimeZonePatternSelectionData {
options,
prefs,
)?;
let zone =
ZonePatternSelectionData::new_with_skeleton(time_zone_style, options, false);
// Always use the short length for time zones when mixed with another field (Date + Time)
let zone_field_set = ZoneFieldSet::from_time_zone_style_and_length(
time_zone_style,
NeoSkeletonLength::Short,
);
let zone = ZonePatternSelectionData::new_with_skeleton(zone_field_set);
let glue = Self::load_glue(glue_provider, locale, options, GlueType::DateTimeZone)?;
Ok(Self::DateTimeZoneGlue {
date,
Expand Down
Loading

0 comments on commit 76a48e8

Please sign in to comment.