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

Bring time zone length behavior up to spec #5563

Merged
merged 3 commits into from
Sep 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
238 changes: 163 additions & 75 deletions components/datetime/src/neo_marker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,13 +254,14 @@
//! ## Time Zone Formatting
//!
//! Here, we configure a [`NeoFormatter`] to format with generic non-location short,
//! which falls back to the offset when unavailable (see [`NeoTimeZoneGenericShortMarker`]).
//! which falls back to the offset when unavailable (see [`NeoTimeZoneGenericMarker`]).
//!
//! ```
//! use icu::calendar::DateTime;
//! use icu::timezone::{CustomTimeZone, MetazoneCalculator, TimeZoneIdMapper, TimeZoneBcp47Id};
//! use icu::datetime::neo::TypedNeoFormatter;
//! use icu::datetime::neo_marker::NeoTimeZoneGenericShortMarker;
//! use icu::datetime::neo_marker::NeoTimeZoneGenericMarker;
//! use icu::datetime::neo_skeleton::NeoSkeletonLength;
//! use icu::datetime::NeverCalendar;
//! use icu::locale::locale;
//! use tinystr::tinystr;
Expand All @@ -280,10 +281,9 @@
//! .unwrap();
//!
//! // Set up the formatter
//! let mut tzf = TypedNeoFormatter::<NeverCalendar, NeoTimeZoneGenericShortMarker>::try_new(
//! let mut tzf = TypedNeoFormatter::<NeverCalendar, NeoTimeZoneGenericMarker>::try_new(
//! &locale!("en").into(),
//! // Length does not matter here: it is specified in the type parameter
//! Default::default(),
//! NeoSkeletonLength::Short.into(),
//! )
//! .unwrap();
//!
Expand Down Expand Up @@ -1782,8 +1782,8 @@ macro_rules! impl_date_marker {
/// ```
$type,
sample_length: $sample_length,
$(alignment: $option_alignment_yes)?,
$(era_display: $year_yes)?,
$(alignment: $option_alignment_yes,)?
$(era_display: $year_yes,)?
);
impl private::Sealed for $type {}
impl DateTimeNamesMarker for $type {
Expand Down Expand Up @@ -2030,8 +2030,7 @@ macro_rules! impl_zone_marker {
// A plain language description of the field set for documentation.
description = $description:literal,
// Length of the sample string below.
// Omit if this field set does not accept a length.
$(sample_length = $sample_length:ident,)?
sample_length = $sample_length:ident,
// A sample string. A docs test will be generated!
sample = $sample:literal,
// Whether zone-essentials should be loaded.
Expand Down Expand Up @@ -2064,7 +2063,7 @@ macro_rules! impl_zone_marker {
///
#[doc = concat!("let fmt = NeoFormatter::<", stringify!($type), ">::try_new(")]
/// &locale!("en").into(),
#[doc = concat!(" ", length_option_helper!($($sample_length)?), ",")]
#[doc = concat!(" ", length_option_helper!($sample_length), ",")]
/// )
/// .unwrap();
///
Expand Down Expand Up @@ -2097,7 +2096,7 @@ macro_rules! impl_zone_marker {
///
#[doc = concat!("let fmt = TypedNeoFormatter::<Gregorian, ", stringify!($type), ">::try_new(")]
/// &locale!("en").into(),
#[doc = concat!(" ", length_option_helper!($($sample_length)?), ",")]
#[doc = concat!(" ", length_option_helper!($sample_length), ",")]
/// )
/// .unwrap();
///
Expand Down Expand Up @@ -2150,7 +2149,7 @@ macro_rules! impl_zone_marker {
type D = NeoNeverMarker;
type T = NeoNeverMarker;
type Z = Self;
type LengthOption = datetime_marker_helper!(@option/length, $($sample_length)?);
type LengthOption = datetime_marker_helper!(@option/length, yes);
type AlignmentOption = datetime_marker_helper!(@option/alignment,);
type EraDisplayOption = datetime_marker_helper!(@option/eradisplay,);
type FractionalSecondDigitsOption = datetime_marker_helper!(@option/fractionalsecondigits,);
Expand Down Expand Up @@ -2327,6 +2326,19 @@ impl_day_marker!(
option_alignment = yes,
);

impl_day_marker!(
NeoMonthDayMarker,
NeoDayComponents::MonthDay,
description = "month and day",
sample_length = Medium,
sample = "May 17",
months = yes,
input_month = yes,
input_day_of_month = yes,
input_any_calendar_kind = yes,
option_alignment = yes,
);

impl_day_marker!(
NeoAutoDateMarker,
NeoDayComponents::Auto,
Expand Down Expand Up @@ -2416,16 +2428,6 @@ impl_date_marker!(
option_alignment = yes,
);

impl_zone_marker!(
NeoTimeZoneSpecificMarker,
NeoTimeZoneSkeleton::specific(),
description = "specific time zone with inherited length, or raw offset if unavailable",
sample_length = Medium,
sample = "CDT",
zone_essentials = yes,
zone_specific_short = yes,
);

impl_zone_marker!(
/// When a display name is unavailable, falls back to the offset format:
///
Expand All @@ -2434,15 +2436,15 @@ impl_zone_marker!(
/// use icu::timezone::{CustomTimeZone, CustomZonedDateTime};
/// use icu::calendar::Gregorian;
/// use icu::datetime::neo::TypedNeoFormatter;
/// use icu::datetime::neo_marker::NeoTimeZoneSpecificShortMarker;
/// use icu::datetime::neo_marker::NeoTimeZoneSpecificMarker;
/// use icu::datetime::neo_skeleton::NeoSkeletonLength;
/// use icu::locale::locale;
/// use tinystr::tinystr;
/// use writeable::assert_try_writeable_eq;
///
/// let fmt = TypedNeoFormatter::<Gregorian, NeoTimeZoneSpecificShortMarker>::try_new(
/// let fmt = TypedNeoFormatter::<Gregorian, NeoTimeZoneSpecificMarker>::try_new(
/// &locale!("en").into(),
/// Default::default(),
/// NeoSkeletonLength::Short.into(),
/// )
/// .unwrap();
///
Expand All @@ -2459,59 +2461,88 @@ impl_zone_marker!(
/// "GMT-03:00"
/// );
/// ```
NeoTimeZoneSpecificShortMarker,
NeoTimeZoneSkeleton::specific_short(),
description = "specific time zone with a shorter length, or raw offset if unavailable",
sample = "CDT",
NeoTimeZoneSpecificMarker,
NeoTimeZoneSkeleton::specific(),
description = "specific time zone, or raw offset if unavailable",
sample_length = Long,
sample = "Central Daylight Time",
zone_essentials = yes,
zone_specific_long = yes,
zone_specific_short = yes,
);

impl_zone_marker!(
NeoTimeZoneSpecificLongMarker,
NeoTimeZoneSkeleton::specific_long(),
description = "specific time zone with a longer length, or raw offset if unavailable",
sample = "Central Daylight Time",
/// This marker only loads data for the short length. Useful when combined with other fields:
///
/// ```
/// use icu::calendar::{Date, Time};
/// use icu::timezone::{CustomTimeZone, CustomZonedDateTime};
/// use icu::calendar::Gregorian;
/// use icu::datetime::neo::NeoFormatter;
/// use icu::datetime::neo_marker::NeoMonthDayMarker;
/// use icu::datetime::neo_marker::NeoHourMinuteMarker;
/// use icu::datetime::neo_marker::NeoTimeZoneSpecificShortMarker;
/// use icu::datetime::neo_marker::DateTimeCombo;
/// use icu::datetime::neo_skeleton::NeoSkeletonLength;
/// use icu::locale::locale;
/// use tinystr::tinystr;
/// use writeable::assert_try_writeable_eq;
///
/// type MyDateTimeZoneSet = DateTimeCombo<
/// NeoMonthDayMarker,
/// NeoHourMinuteMarker,
/// NeoTimeZoneSpecificShortMarker,
/// >;
///
/// let fmt = NeoFormatter::<MyDateTimeZoneSet>::try_new(
/// &locale!("en-US").into(),
/// NeoSkeletonLength::Long.into(),
/// )
/// .unwrap();
///
/// let dtz = CustomZonedDateTime::try_from_str("2024-09-17T15:47:50-05:00[America/Chicago]").unwrap();
///
/// assert_try_writeable_eq!(
/// fmt.convert_and_format(&dtz),
/// "September 17, 3:47 PM CDT"
/// );
/// ```
///
/// Don't use long length if it is the only field:
///
/// ```
/// use icu::calendar::Gregorian;
/// use icu::datetime::neo::TypedNeoFormatter;
/// use icu::datetime::neo_marker::NeoTimeZoneSpecificShortMarker;
/// use icu::datetime::neo_skeleton::NeoSkeletonLength;
/// use icu::datetime::LoadError;
/// use icu::locale::locale;
///
/// let result = TypedNeoFormatter::<Gregorian, NeoTimeZoneSpecificShortMarker>::try_new(
/// &locale!("en").into(),
/// NeoSkeletonLength::Long.into(),
/// );
///
/// assert!(matches!(result, Err(LoadError::TypeTooNarrow(_))));
/// ```
NeoTimeZoneSpecificShortMarker,
NeoTimeZoneSkeleton::specific(),
description = "specific time zone (only short), or raw offset if unavailable",
sample_length = Short,
sample = "CDT",
zone_essentials = yes,
zone_specific_long = yes,
zone_specific_short = yes,
);

impl_zone_marker!(
NeoTimeZoneOffsetMarker,
NeoTimeZoneSkeleton::offset(),
description = "UTC offset with inherited length",
description = "UTC offset time zone",
sample_length = Medium,
sample = "GMT-05:00", // TODO: Implement short localized offset
zone_essentials = yes,
);

impl_zone_marker!(
NeoTimeZoneOffsetShortMarker,
NeoTimeZoneSkeleton::offset_short(),
description = "UTC offset with a shorter length",
sample = "GMT-05:00", // TODO: Implement short localized offset
zone_essentials = yes,
);

impl_zone_marker!(
NeoTimeZoneOffsetLongMarker,
NeoTimeZoneSkeleton::offset_long(),
description = "UTC offset with a longer length",
sample = "GMT-05:00",
zone_essentials = yes,
);

impl_zone_marker!(
NeoTimeZoneGenericMarker,
NeoTimeZoneSkeleton::generic(),
description = "generic time zone with inherited length, or location if unavailable",
sample_length = Medium,
sample = "CT",
zone_essentials = yes,
zone_exemplar_cities = yes,
zone_generic_short = yes,
);

impl_zone_marker!(
/// When a display name is unavailable, falls back to the location format:
///
Expand All @@ -2520,15 +2551,15 @@ impl_zone_marker!(
/// use icu::timezone::{CustomTimeZone, CustomZonedDateTime};
/// use icu::calendar::Gregorian;
/// use icu::datetime::neo::TypedNeoFormatter;
/// use icu::datetime::neo_marker::NeoTimeZoneGenericShortMarker;
/// use icu::datetime::neo_marker::NeoTimeZoneGenericMarker;
/// use icu::datetime::neo_skeleton::NeoSkeletonLength;
/// use icu::locale::locale;
/// use tinystr::tinystr;
/// use writeable::assert_try_writeable_eq;
///
/// let fmt = TypedNeoFormatter::<Gregorian, NeoTimeZoneGenericShortMarker>::try_new(
/// let fmt = TypedNeoFormatter::<Gregorian, NeoTimeZoneGenericMarker>::try_new(
/// &locale!("en").into(),
/// Default::default(),
/// NeoSkeletonLength::Short.into(),
/// )
/// .unwrap();
///
Expand All @@ -2545,29 +2576,86 @@ impl_zone_marker!(
/// "Sao Paulo Time"
/// );
/// ```
NeoTimeZoneGenericShortMarker,
NeoTimeZoneSkeleton::generic_short(),
description = "generic time zone with a shorter length, or location if unavailable",
sample = "CT",
NeoTimeZoneGenericMarker,
NeoTimeZoneSkeleton::generic(),
description = "generic time zone, or location if unavailable",
sample_length = Long,
sample = "Central Time",
zone_essentials = yes,
zone_exemplar_cities = yes,
zone_generic_long = yes,
zone_generic_short = yes,
);

impl_zone_marker!(
NeoTimeZoneGenericLongMarker,
NeoTimeZoneSkeleton::generic_long(),
description = "generic time zone with a longer length, or location if unavailable",
sample = "Central Time",
/// This marker only loads data for the short length. Useful when combined with other fields:
///
/// ```
/// use icu::calendar::{Date, Time};
/// use icu::timezone::{CustomTimeZone, CustomZonedDateTime};
/// use icu::calendar::Gregorian;
/// use icu::datetime::neo::NeoFormatter;
/// use icu::datetime::neo_marker::NeoMonthDayMarker;
/// use icu::datetime::neo_marker::NeoHourMinuteMarker;
/// use icu::datetime::neo_marker::NeoTimeZoneGenericShortMarker;
/// use icu::datetime::neo_marker::DateTimeCombo;
/// use icu::datetime::neo_skeleton::NeoSkeletonLength;
/// use icu::locale::locale;
/// use tinystr::tinystr;
/// use writeable::assert_try_writeable_eq;
///
/// type MyDateTimeZoneSet = DateTimeCombo<
/// NeoMonthDayMarker,
/// NeoHourMinuteMarker,
/// NeoTimeZoneGenericShortMarker,
/// >;
///
/// let fmt = NeoFormatter::<MyDateTimeZoneSet>::try_new(
/// &locale!("en-US").into(),
/// NeoSkeletonLength::Long.into(),
/// )
/// .unwrap();
///
/// let dtz = CustomZonedDateTime::try_from_str("2024-09-17T15:47:50-05:00[America/Chicago]").unwrap();
///
/// assert_try_writeable_eq!(
/// fmt.convert_and_format(&dtz),
/// "September 17, 3:47 PM CT"
/// );
/// ```
///
/// Don't use long length if it is the only field:
///
/// ```
/// use icu::calendar::Gregorian;
/// use icu::datetime::neo::TypedNeoFormatter;
/// use icu::datetime::neo_marker::NeoTimeZoneGenericShortMarker;
/// use icu::datetime::neo_skeleton::NeoSkeletonLength;
/// use icu::datetime::LoadError;
/// use icu::locale::locale;
///
/// let result = TypedNeoFormatter::<Gregorian, NeoTimeZoneGenericShortMarker>::try_new(
/// &locale!("en").into(),
/// NeoSkeletonLength::Long.into(),
/// );
///
/// assert!(matches!(result, Err(LoadError::TypeTooNarrow(_))));
/// ```
NeoTimeZoneGenericShortMarker,
NeoTimeZoneSkeleton::generic(),
description = "generic time zone (only short), or location if unavailable",
sample_length = Short,
sample = "CT",
zone_essentials = yes,
zone_exemplar_cities = yes,
zone_generic_long = yes,
zone_generic_short = yes,
);

impl_zone_marker!(
NeoTimeZoneLocationMarker,
NeoTimeZoneSkeleton::location(),
description = "location time zone",
sample_length = Long,
sample = "Chicago Time",
zone_essentials = yes,
zone_exemplar_cities = yes,
Expand All @@ -2581,7 +2669,7 @@ impl_zoneddatetime_marker!(
sample = "May 17, 2024, 3:47:50 PM GMT",
date = NeoAutoDateMarker,
time = NeoAutoTimeMarker,
zone = NeoTimeZoneGenericShortMarker,
zone = NeoTimeZoneGenericMarker,
);

/// Trait for components that can be formatted at runtime.
Expand Down
Loading
Loading