Skip to content

Commit 95ff80e

Browse files
authored
More datetime cleanups for 2.0 Beta (#5823)
#1317 - Move docs tests from neo_marker to better places - Making Serde impls experimental
1 parent dd0e253 commit 95ff80e

File tree

23 files changed

+591
-450
lines changed

23 files changed

+591
-450
lines changed

components/datetime/Cargo.toml

+3-3
Original file line numberDiff line numberDiff line change
@@ -114,16 +114,16 @@ unexpected_cfgs = { level = "warn", check-cfg = ['cfg(icu4x_run_size_tests)'] }
114114
[[bench]]
115115
name = "datetime"
116116
harness = false
117-
required-features = ["compiled_data"]
117+
required-features = ["compiled_data", "serde", "experimental"]
118118

119119
[[bench]]
120120
name = "pattern"
121121
harness = false
122-
required-features = ["bench"]
122+
required-features = ["bench", "serde", "experimental"]
123123

124124
[[test]]
125125
name = "datetime"
126-
required-features = ["experimental", "compiled_data"]
126+
required-features = ["experimental", "compiled_data", "serde"]
127127

128128
[[test]]
129129
name = "resolved_components"

components/datetime/benches/datetime.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
mod fixtures;
66

77
use criterion::{criterion_group, criterion_main, Criterion};
8-
use icu_datetime::FixedCalendarDateTimeFormatter;
8+
use icu_datetime::{fieldset::dynamic::CompositeFieldSet, FixedCalendarDateTimeFormatter};
99

1010
use icu_calendar::{Date, DateTime, Gregorian, Time};
1111
use icu_locale_core::Locale;
@@ -47,7 +47,8 @@ fn datetime_benches(c: &mut Criterion) {
4747
.collect();
4848
for setup in &fx.setups {
4949
let locale: Locale = setup.locale.parse().expect("Failed to parse locale.");
50-
let skeleton = setup.options.semantic.unwrap();
50+
let skeleton =
51+
CompositeFieldSet::try_from(setup.options.semantic.unwrap()).unwrap();
5152

5253
let dtf = {
5354
FixedCalendarDateTimeFormatter::<Gregorian, _>::try_new(

components/datetime/benches/fixtures/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// called LICENSE at the top level of the ICU4X source tree
33
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
44

5-
use icu_datetime::{options, provider::skeleton::components};
5+
use icu_datetime::{fields::components, fieldset::serde::CompositeFieldSetSerde, options};
66
use serde::{Deserialize, Serialize};
77

88
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
@@ -24,7 +24,7 @@ pub struct TestInput {
2424
pub struct TestOptions {
2525
pub length: Option<TestOptionsLength>,
2626
pub components: Option<TestComponentsBag>,
27-
pub semantic: Option<icu_datetime::fieldset::dynamic::CompositeFieldSet>,
27+
pub semantic: Option<CompositeFieldSetSerde>,
2828
#[serde(rename = "hourCycle")]
2929
pub hour_cycle: Option<TestHourCycle>,
3030
}

components/datetime/src/dynamic.rs

+1-8
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
// called LICENSE at the top level of the ICU4X source tree
33
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
44

5-
#[cfg(feature = "serde")]
6-
use crate::neo_serde::*;
75
use crate::raw::neo::RawNeoOptions;
86
use crate::scaffold::GetField;
97
use crate::{fields, fieldset, NeoSkeletonLength};
@@ -211,11 +209,6 @@ impl GetField<CompositeFieldSet> for CompositeDateTimeFieldSet {
211209

212210
/// An enum supporting all possible field sets and options.
213211
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
214-
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
215-
#[cfg_attr(
216-
feature = "serde",
217-
serde(try_from = "SemanticSkeletonSerde", into = "SemanticSkeletonSerde")
218-
)]
219212
#[non_exhaustive]
220213
pub enum CompositeFieldSet {
221214
/// Field set for a date.
@@ -365,7 +358,7 @@ macro_rules! impl_attrs {
365358
alignment,
366359
})
367360
}
368-
#[cfg(feature = "serde")]
361+
#[cfg(all(feature = "serde", feature = "experimental"))]
369362
pub(crate) fn from_date_field_set_with_raw_options(date_field_set: DateFieldSet, options: RawNeoOptions) -> Self {
370363
match date_field_set {
371364
$(

components/datetime/src/provider/skeleton/components.rs renamed to components/datetime/src/fields/components.rs

+2-16
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// called LICENSE at the top level of the ICU4X source tree
33
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
44

5-
//! Types for specifying fields in a classical datetime skeleton.
5+
//! 🚧 \[Experimental\] Types for specifying fields in a classical datetime skeleton.
66
//!
77
//! <div class="stab unstable">
88
//! 🚧 This code is experimental; it may change at any time, in breaking or non-breaking ways,
@@ -14,7 +14,7 @@
1414
//! # Examples
1515
//!
1616
//! ```
17-
//! use icu::datetime::provider::skeleton::components;
17+
//! use icu::datetime::fields::components;
1818
//!
1919
//! let mut bag = components::Bag::default();
2020
//! bag.year = Some(components::Year::Numeric);
@@ -33,7 +33,6 @@ use crate::{
3333
fields::{self, Field, FieldLength, FieldSymbol},
3434
options::FractionalSecondDigits,
3535
provider::pattern::{runtime::Pattern, PatternItem},
36-
provider::skeleton::PatternPlurals,
3736
};
3837

3938
use crate::neo_pattern::DateTimePattern;
@@ -116,7 +115,6 @@ impl Bag {
116115
///
117116
/// - `default_hour_cycle` specifies the hour cycle to use for the hour field if not in the Bag.
118117
/// `preferences::Bag::hour_cycle` takes precedence over this argument.
119-
#[cfg(feature = "datagen")]
120118
pub fn to_vec_fields(&self, default_hour_cycle: HourCycle) -> alloc::vec::Vec<Field> {
121119
let mut fields = alloc::vec::Vec::new();
122120
if let Some(era) = self.era {
@@ -579,18 +577,6 @@ impl From<TimeZoneName> for Field {
579577
}
580578
}
581579

582-
/// Get the resolved components for a FixedCalendarDateTimeFormatter, via the PatternPlurals. In the case of
583-
/// plurals resolve off of the required `other` pattern.
584-
impl From<&PatternPlurals<'_>> for Bag {
585-
fn from(other: &PatternPlurals) -> Self {
586-
let pattern = match other {
587-
PatternPlurals::SinglePattern(pattern) => pattern,
588-
PatternPlurals::MultipleVariants(plural_pattern) => &plural_pattern.other,
589-
};
590-
Self::from(pattern)
591-
}
592-
}
593-
594580
impl From<&DateTimePattern> for Bag {
595581
fn from(value: &DateTimePattern) -> Self {
596582
Self::from(value.as_borrowed().0)

components/datetime/src/fields/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ use displaydoc::Display;
1313
pub use length::{FieldLength, FieldNumericOverrides, LengthError};
1414
pub use symbols::*;
1515

16+
#[cfg(any(feature = "experimental", feature = "datagen"))]
17+
pub mod components;
18+
1619
use core::{
1720
cmp::{Ord, PartialOrd},
1821
convert::TryFrom,

components/datetime/src/fieldset.rs

+145
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,19 @@ pub mod dynamic {
3030
pub use crate::dynamic::*;
3131
}
3232

33+
/// 🚧 \[Experimental\] Types for dealing with serialization of semantic skeletons.
34+
///
35+
/// <div class="stab unstable">
36+
/// 🚧 This code is experimental; it may change at any time, in breaking or non-breaking ways,
37+
/// including in SemVer minor releases. Use with caution.
38+
/// <a href="https://github.com/unicode-org/icu4x/issues/5825">#5825</a>
39+
/// </div>
40+
#[cfg(all(feature = "experimental", feature = "serde"))]
41+
pub mod serde {
42+
pub use crate::neo_serde::CompositeFieldSetSerde;
43+
pub use crate::neo_serde::CompositeFieldSetSerdeError;
44+
}
45+
3346
#[cfg(doc)]
3447
use icu_timezone::TimeZoneInfo;
3548

@@ -1147,6 +1160,88 @@ impl_calendar_period_marker!(
11471160
);
11481161

11491162
impl_time_marker!(
1163+
/// Hours can be switched between 12-hour and 24-hour time via the `u-hc` locale keyword.
1164+
///
1165+
/// ```
1166+
/// use icu::calendar::Time;
1167+
/// use icu::datetime::fieldset::T;
1168+
/// use icu::datetime::FixedCalendarDateTimeFormatter;
1169+
/// use icu::locale::locale;
1170+
/// use writeable::assert_try_writeable_eq;
1171+
///
1172+
/// // By default, en-US uses 12-hour time and fr-FR uses 24-hour time,
1173+
/// // but we can set overrides.
1174+
///
1175+
/// let formatter = FixedCalendarDateTimeFormatter::<(), _>::try_new(
1176+
/// &locale!("en-US-u-hc-h12").into(),
1177+
/// T::short().hm(),
1178+
/// )
1179+
/// .unwrap();
1180+
/// assert_try_writeable_eq!(
1181+
/// formatter.format(&Time::try_new(16, 12, 20, 0).unwrap()),
1182+
/// "4:12 PM"
1183+
/// );
1184+
///
1185+
/// let formatter = FixedCalendarDateTimeFormatter::<(), _>::try_new(
1186+
/// &locale!("en-US-u-hc-h23").into(),
1187+
/// T::short().hm(),
1188+
/// )
1189+
/// .unwrap();
1190+
/// assert_try_writeable_eq!(
1191+
/// formatter.format(&Time::try_new(16, 12, 20, 0).unwrap()),
1192+
/// "16:12"
1193+
/// );
1194+
///
1195+
/// let formatter = FixedCalendarDateTimeFormatter::<(), _>::try_new(
1196+
/// &locale!("fr-FR-u-hc-h12").into(),
1197+
/// T::short().hm(),
1198+
/// )
1199+
/// .unwrap();
1200+
/// assert_try_writeable_eq!(
1201+
/// formatter.format(&Time::try_new(16, 12, 20, 0).unwrap()),
1202+
/// "4:12 PM"
1203+
/// );
1204+
///
1205+
/// let formatter = FixedCalendarDateTimeFormatter::<(), _>::try_new(
1206+
/// &locale!("fr-FR-u-hc-h23").into(),
1207+
/// T::short().hm(),
1208+
/// )
1209+
/// .unwrap();
1210+
/// assert_try_writeable_eq!(
1211+
/// formatter.format(&Time::try_new(16, 12, 20, 0).unwrap()),
1212+
/// "16:12"
1213+
/// );
1214+
/// ```
1215+
///
1216+
/// Hour cycles `h11` and `h24` are supported, too:
1217+
///
1218+
/// ```
1219+
/// use icu::calendar::Time;
1220+
/// use icu::datetime::fieldset::T;
1221+
/// use icu::datetime::FixedCalendarDateTimeFormatter;
1222+
/// use icu::locale::locale;
1223+
/// use writeable::assert_try_writeable_eq;
1224+
///
1225+
/// let formatter = FixedCalendarDateTimeFormatter::<(), _>::try_new(
1226+
/// &locale!("und-u-hc-h11").into(),
1227+
/// T::short().hm(),
1228+
/// )
1229+
/// .unwrap();
1230+
/// assert_try_writeable_eq!(
1231+
/// formatter.format(&Time::try_new(0, 0, 0, 0).unwrap()),
1232+
/// "0:00 AM"
1233+
/// );
1234+
///
1235+
/// let formatter = FixedCalendarDateTimeFormatter::<(), _>::try_new(
1236+
/// &locale!("und-u-hc-h24").into(),
1237+
/// T::short().hm(),
1238+
/// )
1239+
/// .unwrap();
1240+
/// assert_try_writeable_eq!(
1241+
/// formatter.format(&Time::try_new(0, 0, 0, 0).unwrap()),
1242+
/// "24:00"
1243+
/// );
1244+
/// ```
11501245
T,
11511246
NeoTimeComponents::Time,
11521247
description = "time (locale-dependent hour cycle)",
@@ -1381,6 +1476,56 @@ impl_zone_marker!(
13811476
/// );
13821477
/// ```
13831478
///
1479+
/// Can also fall back to the UTC offset:
1480+
///
1481+
/// ```
1482+
/// use icu::calendar::{Date, Time};
1483+
/// use icu::timezone::{TimeZoneInfo, UtcOffset, TimeZoneIdMapper, TimeZoneBcp47Id};
1484+
/// use icu::datetime::FixedCalendarDateTimeFormatter;
1485+
/// use icu::datetime::fieldset::V;
1486+
/// use icu::datetime::DateTimeWriteError;
1487+
/// use icu::locale::locale;
1488+
/// use tinystr::tinystr;
1489+
/// use writeable::assert_try_writeable_eq;
1490+
///
1491+
/// // Set up the formatter
1492+
/// let mut tzf = FixedCalendarDateTimeFormatter::<(), _>::try_new(
1493+
/// &locale!("en").into(),
1494+
/// V::short(),
1495+
/// )
1496+
/// .unwrap();
1497+
///
1498+
/// // "uschi" - has symbol data for short generic non-location
1499+
/// let time_zone = TimeZoneIdMapper::new()
1500+
/// .iana_to_bcp47("America/Chicago")
1501+
/// .with_offset("-05".parse().ok())
1502+
/// .at_time((Date::try_new_iso(2022, 8, 29).unwrap(), Time::midnight()));
1503+
/// assert_try_writeable_eq!(
1504+
/// tzf.format(&time_zone),
1505+
/// "CT"
1506+
/// );
1507+
///
1508+
/// // "ushnl" - has time zone override symbol data for short generic non-location
1509+
/// let time_zone = TimeZoneIdMapper::new()
1510+
/// .iana_to_bcp47("Pacific/Honolulu")
1511+
/// .with_offset("-10".parse().ok())
1512+
/// .at_time((Date::try_new_iso(2022, 8, 29).unwrap(), Time::midnight()));
1513+
/// assert_try_writeable_eq!(
1514+
/// tzf.format(&time_zone),
1515+
/// "HST"
1516+
/// );
1517+
///
1518+
/// // Mis-spelling of "America/Chicago" results in a fallback to offset format
1519+
/// let time_zone = TimeZoneIdMapper::new()
1520+
/// .iana_to_bcp47("America/Chigagou")
1521+
/// .with_offset("-05".parse().ok())
1522+
/// .at_time((Date::try_new_iso(2022, 8, 29).unwrap(), Time::midnight()));
1523+
/// assert_try_writeable_eq!(
1524+
/// tzf.format(&time_zone),
1525+
/// "GMT-5"
1526+
/// );
1527+
/// ```
1528+
///
13841529
/// Since non-location names might change over time,
13851530
/// this time zone style requires a reference time.
13861531
///

components/datetime/src/lib.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,8 @@ pub mod fieldset;
9696
mod format;
9797
pub mod input;
9898
mod neo;
99-
mod neo_marker;
10099
pub mod neo_pattern;
101-
#[cfg(feature = "serde")]
100+
#[cfg(all(feature = "experimental", feature = "serde"))]
102101
mod neo_serde;
103102
pub mod options;
104103
pub mod provider;

0 commit comments

Comments
 (0)