#![cfg(feature = "serde")]
mod fixtures;
mod patterns;
use icu_datetime::{
mock::{datetime::MockDateTime, zoned_datetime::MockZonedDateTime},
DateTimeFormatOptions, ZonedDateTimeFormat,
};
use icu_datetime::{
provider::{gregory::DatesV1, key::GREGORY_V1},
DateTimeFormat,
};
use icu_locid::{LanguageIdentifier, Locale};
use icu_provider::{
struct_provider::StructProvider, DataProvider, DataRequest, ResourceOptions, ResourcePath,
};
use patterns::{
get_dayperiod_tests, get_time_zone_tests,
structs::{
dayperiods::DayPeriodExpectation,
time_zones::{TimeZoneConfig, TimeZoneExpectation},
},
};
use std::{borrow::Cow, fmt::Write};
fn test_fixture(fixture_name: &str) {
let provider = icu_testdata::get_provider();
for fx in fixtures::get_fixture(fixture_name)
.expect("Unable to get fixture.")
.0
{
let locale: Locale = fx.input.locale.parse().unwrap();
let options = fixtures::get_options(&fx.input.options);
let dtf = DateTimeFormat::try_new(locale, &provider, &options).unwrap();
let value: MockDateTime = fx.input.value.parse().unwrap();
let result = dtf.format_to_string(&value);
match fx.description {
Some(description) => assert_eq!(
result, fx.output.value,
"expected {:?} to equal {:?} – {}",
result, fx.output.value, description
),
None => assert_eq!(result, fx.output.value),
}
let mut s = String::new();
dtf.format_to_write(&mut s, &value).unwrap();
assert_eq!(s, fx.output.value, "\n file: {}.json\n", fixture_name);
let fdt = dtf.format(&value);
let s = fdt.to_string();
assert_eq!(s, fx.output.value, "\n file: {}.json\n", fixture_name);
let mut s = String::new();
write!(s, "{}", fdt).unwrap();
assert_eq!(s, fx.output.value, "\n file: {}.json\n", fixture_name);
}
}
fn test_fixture_with_time_zones(fixture_name: &str, config: TimeZoneConfig) {
let provider = icu_testdata::get_provider();
for fx in fixtures::get_fixture(fixture_name)
.expect("Unable to get fixture.")
.0
{
let locale: Locale = fx.input.locale.parse().unwrap();
let options = fixtures::get_options(&fx.input.options);
let dtf = ZonedDateTimeFormat::try_new(locale, &provider, &provider, &options).unwrap();
let mut value: MockZonedDateTime = fx.input.value.parse().unwrap();
value.time_zone.time_zone_id = config.time_zone_id.clone();
value.time_zone.metazone_id = config.metazone_id.clone();
value.time_zone.time_variant = config.time_variant.clone();
let result = dtf.format_to_string(&value);
assert_eq!(result, fx.output.value, "\n file: {}.json\n", fixture_name);
let mut s = String::new();
dtf.format_to_write(&mut s, &value).unwrap();
assert_eq!(s, fx.output.value, "\n file: {}.json\n", fixture_name);
let fdt = dtf.format(&value);
let s = fdt.to_string();
assert_eq!(s, fx.output.value, "\n file: {}.json\n", fixture_name);
let mut s = String::new();
write!(s, "{}", fdt).unwrap();
assert_eq!(s, fx.output.value, "\n file: {}.json\n", fixture_name);
}
}
#[test]
fn test_dayperiod_patterns() {
let provider = icu_testdata::get_provider();
let format_options = DateTimeFormatOptions::default();
for test in get_dayperiod_tests("dayperiods").unwrap().0 {
let langid: LanguageIdentifier = test.locale.parse().unwrap();
let mut data: Cow<DatesV1> = provider
.load_payload(&DataRequest {
resource_path: ResourcePath {
key: GREGORY_V1,
options: ResourceOptions {
variant: None,
langid: Some(langid.clone()),
},
},
})
.unwrap()
.payload
.take()
.unwrap();
*data
.to_mut()
.patterns
.datetime
.length_patterns
.long
.to_mut() = String::from("{0}");
for test_case in &test.test_cases {
for dt_input in &test_case.datetimes {
let datetime: MockDateTime = dt_input.parse().unwrap();
for DayPeriodExpectation { patterns, expected } in &test_case.expectations {
for pattern_input in patterns {
*data.to_mut().patterns.time.long.to_mut() = String::from(pattern_input);
let provider = StructProvider {
key: GREGORY_V1,
data: data.as_ref(),
};
let dtf =
DateTimeFormat::try_new(langid.clone(), &provider, &format_options)
.unwrap();
assert_eq!(
dtf.format(&datetime).to_string(),
*expected,
"\n\
locale: `{}`,\n\
datetime: `{}`,\n\
pattern: `{}`",
langid,
dt_input,
pattern_input,
);
}
}
}
}
}
}
#[test]
fn test_time_zone_patterns() {
let date_provider = icu_testdata::get_provider();
let zone_provider = icu_testdata::get_provider();
let format_options = DateTimeFormatOptions::default();
for test in get_time_zone_tests("time_zones").unwrap().0 {
let langid: LanguageIdentifier = test.locale.parse().unwrap();
let mut config = test.config;
let mut datetime: MockZonedDateTime = test.datetime.parse().unwrap();
datetime.time_zone.time_zone_id = config.time_zone_id.take();
datetime.time_zone.metazone_id = config.metazone_id.take();
datetime.time_zone.time_variant = config.time_variant.take();
let mut data: Cow<DatesV1> = date_provider
.load_payload(&DataRequest {
resource_path: ResourcePath {
key: GREGORY_V1,
options: ResourceOptions {
variant: None,
langid: Some(langid.clone()),
},
},
})
.unwrap()
.payload
.take()
.unwrap();
*data
.to_mut()
.patterns
.datetime
.length_patterns
.long
.to_mut() = String::from("{0}");
for TimeZoneExpectation { patterns, expected } in &test.expectations {
for pattern_input in patterns {
*data.to_mut().patterns.time.long.to_mut() = String::from(pattern_input);
let date_provider = StructProvider {
key: GREGORY_V1,
data: data.as_ref(),
};
let dtf = ZonedDateTimeFormat::try_new(
langid.clone(),
&date_provider,
&zone_provider,
&format_options,
)
.unwrap();
assert_eq!(
dtf.format(&datetime).to_string(),
*expected,
"\n\
locale: `{}`,\n\
datetime: `{}`,\n\
pattern: `{}`",
langid,
test.datetime,
pattern_input,
);
}
}
}
}
#[test]
fn test_length_fixtures() {
test_fixture("lengths");
test_fixture_with_time_zones("lengths_with_zones", TimeZoneConfig::default());
test_fixture_with_time_zones(
"lengths_with_zones_from_pdt",
TimeZoneConfig {
metazone_id: Some(String::from("America_Pacific")),
time_variant: Some(String::from("daylight")),
..TimeZoneConfig::default()
},
);
}
#[test]
fn test_components_exact_matches() {
test_fixture("components-exact-matches");
}
#[test]
#[should_panic]
fn test_components_width_differences() {
test_fixture("components-width-differences");
}
#[test]
fn test_components_combine_datetime() {
test_fixture("components-combine-date-time");
}
#[test]
fn constructing_datetime_format_with_time_zone_pattern_symbols_is_err() {
use icu_datetime::{
options::length::{Bag, Time},
DateTimeFormatOptions,
};
use icu_locid::Locale;
use icu_locid_macros::langid;
let options = DateTimeFormatOptions::Length(Bag {
time: Some(Time::Full),
..Default::default()
});
let locale: Locale = langid!("en").into();
let provider = icu_testdata::get_provider();
let result = DateTimeFormat::try_new(locale, &provider, &options);
assert!(result.is_err());
}