use icu_calendar::Date;
use icu_datetime::fieldsets;
use icu_datetime::input::{DateTime, Time};
use icu_datetime::range::{DateRangeFormatter, FixedCalendarDateRangeFormatter};
use icu_locale_core::locale;
use writeable::assert_writeable_eq;
#[test]
fn test_date_range_gregorian() {
let start = DateTime {
date: Date::try_new_gregorian(2023, 12, 22).unwrap(),
time: Time::try_new(9, 0, 0, 0).unwrap(),
};
let end_same_day = DateTime {
date: Date::try_new_gregorian(2023, 12, 22).unwrap(),
time: Time::try_new(17, 0, 0, 0).unwrap(),
};
let end_next_day = DateTime {
date: Date::try_new_gregorian(2023, 12, 23).unwrap(),
time: Time::try_new(17, 0, 0, 0).unwrap(),
};
let end_next_month = DateTime {
date: Date::try_new_gregorian(2024, 1, 5).unwrap(),
time: Time::try_new(17, 0, 0, 0).unwrap(),
};
{
let fmt = FixedCalendarDateRangeFormatter::try_new(
locale!("en").into(),
fieldsets::YMD::medium(),
)
.unwrap();
assert_writeable_eq!(fmt.format(&start, &end_same_day), "Dec 22, 2023");
assert_writeable_eq!(
fmt.format(&start, &end_next_day),
"Dec 22\u{2009}–\u{2009}23, 2023"
);
assert_writeable_eq!(
fmt.format(&start, &end_next_month),
"Dec 22, 2023\u{2009}–\u{2009}Jan 5, 2024"
);
}
{
let fmt =
FixedCalendarDateRangeFormatter::try_new(locale!("en").into(), fieldsets::T::hm())
.unwrap();
assert_writeable_eq!(
fmt.format(&start.time, &end_same_day.time),
"9:00\u{202f}AM\u{2009}–\u{2009}5:00\u{202f}PM"
);
let end_same_am = Time::try_new(11, 0, 0, 0).unwrap();
assert_writeable_eq!(
fmt.format(&start.time, &end_same_am),
"9:00\u{2009}–\u{2009}11:00\u{202f}AM"
);
assert_writeable_eq!(
fmt.format(&start, &end_next_day),
"9:00\u{202f}AM\u{2009}–\u{2009}5:00\u{202f}PM"
);
}
{
let fmt = FixedCalendarDateRangeFormatter::try_new(
locale!("en").into(),
fieldsets::YMDT::medium(),
)
.unwrap();
assert_writeable_eq!(
fmt.format(&start, &end_same_day),
"Dec 22, 2023, 9:00\u{202f}AM\u{2009}–\u{2009}5:00\u{202f}PM"
);
assert_writeable_eq!(
fmt.format(&start, &end_next_day),
"Dec 22, 2023, 9:00:00\u{202f}AM\u{2009}–\u{2009}Dec 23, 2023, 5:00:00\u{202f}PM"
);
}
{
let fmt = FixedCalendarDateRangeFormatter::try_new(
locale!("en").into(),
fieldsets::YMD::medium(),
)
.unwrap();
assert_writeable_eq!(fmt.format(&start, &end_same_day), "Dec 22, 2023");
}
}
#[test]
fn test_date_range_any_calendar_dynamic_conversion() {
let start = DateTime {
date: Date::try_new_gregorian(2023, 12, 22).unwrap(),
time: Time::try_new(9, 0, 0, 0).unwrap(),
};
let end_next_day = DateTime {
date: Date::try_new_gregorian(2023, 12, 23).unwrap(),
time: Time::try_new(17, 0, 0, 0).unwrap(),
};
let fmt =
DateRangeFormatter::try_new(locale!("th-u-ca-buddhist").into(), fieldsets::YMD::medium())
.unwrap();
assert_writeable_eq!(fmt.format(&start, &end_next_day), "22–23 ธ.ค. 2566");
}
#[test]
fn test_date_range_timezone() {
use icu_calendar::Date;
use icu_datetime::fieldsets;
use icu_datetime::input::Time;
use icu_datetime::range::FixedCalendarDateRangeFormatter;
use icu_locale_core::locale;
use icu_time::zone::UtcOffset;
use icu_time::{TimeZone, ZonedDateTime};
use writeable::assert_writeable_eq;
let zone1 = TimeZone::from_iana_id("Europe/Paris")
.with_offset(Some(UtcOffset::try_from_seconds(3600).unwrap())); let zone2 = TimeZone::from_iana_id("Europe/Athens")
.with_offset(Some(UtcOffset::try_from_seconds(7200).unwrap()));
let start = ZonedDateTime {
date: Date::try_new_gregorian(2023, 12, 22).unwrap(),
time: Time::try_new(9, 0, 0, 0).unwrap(),
zone: zone1,
};
let end = ZonedDateTime {
date: Date::try_new_gregorian(2023, 12, 22).unwrap(),
time: Time::try_new(17, 0, 0, 0).unwrap(),
zone: zone2,
};
let fmt = FixedCalendarDateRangeFormatter::try_new(
locale!("en").into(),
fieldsets::YMDT::medium().with_zone(fieldsets::zone::LocalizedOffsetShort),
)
.unwrap();
assert_writeable_eq!(
fmt.format(&start, &end),
"Dec 22, 2023, 9:00:00\u{202f}AM GMT+1\u{2009}–\u{2009}Dec 22, 2023, 5:00:00\u{202f}PM GMT+2"
);
}
#[test]
fn test_date_range_hebrew_leap() {
use icu_calendar::Date;
use icu_calendar::cal::Hebrew;
use icu_datetime::fieldsets;
use icu_datetime::input::{DateTime, Time};
use icu_datetime::range::FixedCalendarDateRangeFormatter;
use icu_locale_core::locale;
use writeable::assert_writeable_eq;
let start_greg = Date::try_new_gregorian(2011, 3, 4).unwrap();
let end_greg = Date::try_new_gregorian(2011, 4, 3).unwrap();
let start = DateTime {
date: start_greg.to_calendar(Hebrew),
time: Time::try_new(9, 0, 0, 0).unwrap(),
};
let end = DateTime {
date: end_greg.to_calendar(Hebrew),
time: Time::try_new(17, 0, 0, 0).unwrap(),
};
let fmt =
FixedCalendarDateRangeFormatter::try_new(locale!("en").into(), fieldsets::YMD::medium())
.unwrap();
assert_writeable_eq!(
fmt.format(&start, &end),
"28 Adar I\u{2009}–\u{2009}28 Adar II 5771"
);
}
#[test]
fn test_minute_optional_hour_cycle() {
use icu_datetime::options::TimePrecision;
use icu_datetime::range::NoCalendarRangeFormatter;
let time = Time::try_new(7, 0, 0, 0).unwrap();
let time_hour_diff = Time::try_new(8, 0, 0, 0).unwrap();
let time_minute_diff = Time::try_new(7, 15, 0, 0).unwrap();
let fs = fieldsets::T::short().with_time_precision(TimePrecision::MinuteOptional);
let fmt_en = NoCalendarRangeFormatter::try_new(locale!("en-US").into(), fs).unwrap();
assert_writeable_eq!(
fmt_en.format(&time, &time_hour_diff),
"7\u{2009}–\u{2009}8\u{202f}AM"
);
assert_writeable_eq!(
fmt_en.format(&time, &time_minute_diff),
"7:00\u{2009}–\u{2009}7:15\u{202f}AM"
);
let fmt_fr = NoCalendarRangeFormatter::try_new(locale!("fr").into(), fs).unwrap();
assert_writeable_eq!(
fmt_fr.format(&time, &time_hour_diff),
"07:00\u{2009}–\u{2009}08:00"
);
assert_writeable_eq!(
fmt_fr.format(&time, &time_minute_diff),
"07:00\u{2009}–\u{2009}07:15"
);
let fmt_en_h23 =
NoCalendarRangeFormatter::try_new(locale!("en-US-u-hc-h23").into(), fs).unwrap();
assert_writeable_eq!(
fmt_en_h23.format(&time, &time_hour_diff),
"07:00\u{2009}–\u{2009}08:00"
);
assert_writeable_eq!(
fmt_en_h23.format(&time, &time_minute_diff),
"07:00\u{2009}–\u{2009}07:15"
);
let fmt_fr_12 = NoCalendarRangeFormatter::try_new(locale!("fr-u-hc-h12").into(), fs).unwrap();
assert_writeable_eq!(
fmt_fr_12.format(&time, &time_hour_diff),
"7\u{2009}–\u{2009}8\u{202f}AM"
);
assert_writeable_eq!(
fmt_fr_12.format(&time, &time_minute_diff),
"7:00\u{2009}–\u{2009}7:15\u{202f}AM"
);
let fmt_fr_h11 = NoCalendarRangeFormatter::try_new(locale!("fr-u-hc-h11").into(), fs).unwrap();
assert_writeable_eq!(
fmt_fr_h11.format(&time, &time_hour_diff),
"7\u{2009}–\u{2009}8\u{202f}AM"
);
assert_writeable_eq!(
fmt_fr_h11.format(&time, &time_minute_diff),
"7:00\u{2009}–\u{2009}7:15\u{202f}AM"
);
let fmt_en_c24 =
NoCalendarRangeFormatter::try_new(locale!("en-US-u-hc-c24").into(), fs).unwrap();
assert_writeable_eq!(
fmt_en_c24.format(&time, &time_hour_diff),
"07:00\u{2009}–\u{2009}08:00"
);
assert_writeable_eq!(
fmt_en_c24.format(&time, &time_minute_diff),
"07:00\u{2009}–\u{2009}07:15"
);
let fmt_fr_c12 = NoCalendarRangeFormatter::try_new(locale!("fr-u-hc-c12").into(), fs).unwrap();
assert_writeable_eq!(
fmt_fr_c12.format(&time, &time_hour_diff),
"7\u{2009}–\u{2009}8\u{202f}AM"
);
assert_writeable_eq!(
fmt_fr_c12.format(&time, &time_minute_diff),
"7:00\u{2009}–\u{2009}7:15\u{202f}AM"
);
}
#[test]
fn test_date_range_ej() {
use icu_calendar::Date;
use icu_datetime::fieldsets;
use icu_datetime::input::{DateTime, Time};
use icu_datetime::range::{DateRangeFormatter, FixedCalendarDateRangeFormatter};
use icu_locale_core::locale;
use writeable::assert_writeable_eq;
let start_greg = Date::try_new_gregorian(2024, 8, 9).unwrap(); let end_greg = Date::try_new_gregorian(2024, 8, 10).unwrap();
let start = DateTime {
date: start_greg,
time: Time::try_new(20, 40, 0, 0).unwrap(),
};
let end_same_day = DateTime {
date: start_greg,
time: Time::try_new(21, 50, 0, 0).unwrap(),
};
let end_next_day = DateTime {
date: end_greg,
time: Time::try_new(21, 50, 0, 0).unwrap(),
};
let fs = fieldsets::E::short().with_time_hm();
let fmt = FixedCalendarDateRangeFormatter::try_new(locale!("en-US").into(), fs).unwrap();
let any_cal_fmt = DateRangeFormatter::try_new(locale!("en-US").into(), fs).unwrap();
assert_writeable_eq!(
fmt.format(&start, &end_same_day),
"Fri 8:40\u{202f}PM\u{2009}–\u{2009}Fri 9:50\u{202f}PM"
);
assert_writeable_eq!(
fmt.format(&start, &end_next_day),
"Fri 8:40\u{202f}PM\u{2009}–\u{2009}Sat 9:50\u{202f}PM"
);
assert_writeable_eq!(
any_cal_fmt.format(&start, &end_same_day),
"Fri 8:40\u{202f}PM\u{2009}–\u{2009}Fri 9:50\u{202f}PM"
);
assert_writeable_eq!(
any_cal_fmt.format(&start, &end_next_day),
"Fri 8:40\u{202f}PM\u{2009}–\u{2009}Sat 9:50\u{202f}PM"
);
}
#[cfg(debug_assertions)]
#[test]
#[should_panic(expected = "unexpected error in FormattedSingleSide: NamesNotLoaded")]
fn test_root_fallback_names_not_loaded_zh() {
use icu_calendar::Date;
use icu_datetime::fieldsets;
use icu_datetime::input::{DateTime, Time};
use icu_datetime::range::DateRangeFormatter;
use icu_locale_core::locale;
let start = DateTime {
date: Date::try_new_gregorian(2023, 12, 22).unwrap(),
time: Time::try_new(9, 0, 0, 0).unwrap(),
};
let end_day = DateTime {
date: Date::try_new_gregorian(2023, 12, 23).unwrap(),
time: Time::try_new(17, 0, 0, 0).unwrap(),
};
let fmt_zh =
DateRangeFormatter::try_new(locale!("zh").into(), fieldsets::YMD::medium()).unwrap();
let _ = fmt_zh.format(&start, &end_day).to_string();
}
#[cfg(debug_assertions)]
#[test]
#[should_panic(expected = "unexpected error in FormattedSingleSide: NamesNotLoaded")]
fn test_root_fallback_names_not_loaded_es_hebrew() {
use icu_calendar::Date;
use icu_datetime::fieldsets;
use icu_datetime::input::{DateTime, Time};
use icu_datetime::range::DateRangeFormatter;
use icu_locale_core::locale;
let start = DateTime {
date: Date::try_new_gregorian(2023, 12, 22).unwrap(),
time: Time::try_new(9, 0, 0, 0).unwrap(),
};
let end_day = DateTime {
date: Date::try_new_gregorian(2023, 12, 23).unwrap(),
time: Time::try_new(17, 0, 0, 0).unwrap(),
};
let fmt_es_hebrew =
DateRangeFormatter::try_new(locale!("es-u-ca-hebrew").into(), fieldsets::YMD::long())
.unwrap();
let _ = fmt_es_hebrew.format(&start, &end_day).to_string();
}
#[cfg(debug_assertions)]
#[test]
#[should_panic(expected = "unexpected error in FormattedSingleSide: NamesNotLoaded")]
fn test_root_fallback_names_not_loaded_de_buddhist() {
use icu_calendar::Date;
use icu_datetime::fieldsets;
use icu_datetime::input::{DateTime, Time};
use icu_datetime::range::DateRangeFormatter;
use icu_locale_core::locale;
let start = DateTime {
date: Date::try_new_gregorian(2023, 12, 22).unwrap(),
time: Time::try_new(9, 0, 0, 0).unwrap(),
};
let end_day = DateTime {
date: Date::try_new_gregorian(2023, 12, 23).unwrap(),
time: Time::try_new(17, 0, 0, 0).unwrap(),
};
let fmt_de_buddhist =
DateRangeFormatter::try_new(locale!("de-u-ca-buddhist").into(), fieldsets::YMD::long())
.unwrap();
let _ = fmt_de_buddhist.format(&start, &end_day).to_string();
}
#[test]
fn test_root_fallback_issues_field_order() {
use icu_calendar::Date;
use icu_datetime::fieldsets;
use icu_datetime::input::{DateTime, Time};
use icu_datetime::range::DateRangeFormatter;
use icu_locale_core::locale;
use writeable::assert_writeable_eq;
let start = DateTime {
date: Date::try_new_gregorian(2023, 12, 22).unwrap(),
time: Time::try_new(9, 0, 0, 0).unwrap(),
};
let end_day = DateTime {
date: Date::try_new_gregorian(2023, 12, 23).unwrap(),
time: Time::try_new(17, 0, 0, 0).unwrap(),
};
let fmt_de_buddhist =
DateRangeFormatter::try_new(locale!("de-u-ca-buddhist").into(), fieldsets::YMD::medium())
.unwrap();
assert_writeable_eq!(
fmt_de_buddhist.format(&start, &end_day),
"BE 2566-12-22\u{2009}–\u{2009}2566-12-23"
);
let fmt_de_hebrew =
DateRangeFormatter::try_new(locale!("de-u-ca-hebrew").into(), fieldsets::YMD::medium())
.unwrap();
assert_writeable_eq!(
fmt_de_hebrew.format(&start, &end_day),
"AM 5784-04-10\u{2009}–\u{2009}5784-04-11"
);
}