summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimothy Flynn <trflynn89@pm.me>2022-01-10 08:02:01 -0500
committerLinus Groh <mail@linusgroh.de>2022-01-10 16:18:05 +0100
commit05de9b82b871c3967e7c739c2d21db0621248ded (patch)
tree96820a5f7ec754ff9597643d94a1876f9c597ce0
parent15947aa1f0e53c2aaa33c824b960751e47b7c23c (diff)
downloadserenity-05de9b82b871c3967e7c739c2d21db0621248ded.zip
LibJS: Include hour-cycle in DateTimeFormat options
This is a normative change to the Intl spec: https://github.com/tc39/ecma402/commit/20e5c26 Note that this doesn't actually affect us. Its purpose is to provide the hour-cycle to BestFitFormatMatcher. This AO is implementation defined, and ours just invokes BasicFormatMatcher, which doesn't use this field. We could now have LibUnicode generate this field and use it to find a better format pattern, though.
-rw-r--r--Userland/Libraries/LibJS/Runtime/Intl/DateTimeFormat.cpp177
1 files changed, 86 insertions, 91 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/Intl/DateTimeFormat.cpp b/Userland/Libraries/LibJS/Runtime/Intl/DateTimeFormat.cpp
index 99538d894b..846c45cfa5 100644
--- a/Userland/Libraries/LibJS/Runtime/Intl/DateTimeFormat.cpp
+++ b/Userland/Libraries/LibJS/Runtime/Intl/DateTimeFormat.cpp
@@ -179,7 +179,7 @@ ThrowCompletionOr<DateTimeFormat*> initialize_date_time_format(GlobalObject& glo
// 27. Set dateTimeFormat.[[TimeZone]] to timeZone.
date_time_format.set_time_zone(move(time_zone));
- // 28. Let opt be a new Record.
+ // 28. Let formatOptions be a new Record.
Unicode::CalendarPattern format_options {};
// 29. For each row of Table 4, except the header row, in table order, do
@@ -193,7 +193,7 @@ ThrowCompletionOr<DateTimeFormat*> initialize_date_time_format(GlobalObject& glo
// i. Let value be ? GetNumberOption(options, "fractionalSecondDigits", 1, 3, undefined).
auto value = TRY(get_number_option(global_object, *options, property, 1, 3, {}));
- // d. Set opt.[[<prop>]] to value.
+ // d. Set formatOptions.[[<prop>]] to value.
if (value.has_value())
option = static_cast<ValueType>(value.value());
}
@@ -202,7 +202,7 @@ ThrowCompletionOr<DateTimeFormat*> initialize_date_time_format(GlobalObject& glo
// i. Let value be ? GetOption(options, prop, "string", « the strings given in the Values column of the row », undefined).
auto value = TRY(get_option(global_object, *options, property, Value::Type::String, defaults, Empty {}));
- // d. Set opt.[[<prop>]] to value.
+ // d. Set formatOptions.[[<prop>]] to value.
if (!value.is_undefined())
option = Unicode::calendar_pattern_style_from_string(value.as_string().string());
}
@@ -212,31 +212,81 @@ ThrowCompletionOr<DateTimeFormat*> initialize_date_time_format(GlobalObject& glo
// 30. Let dataLocaleData be localeData.[[<dataLocale>]].
- // 31. Let matcher be ? GetOption(options, "formatMatcher", "string", « "basic", "best fit" », "best fit").
+ // 31. Let hcDefault be dataLocaleData.[[hourCycle]].
+ auto default_hour_cycle = Unicode::get_default_regional_hour_cycle(data_locale);
+
+ // Non-standard, default_hour_cycle will be empty if Unicode data generation is disabled.
+ if (!default_hour_cycle.has_value())
+ return &date_time_format;
+
+ // 32. Let hc be dateTimeFormat.[[HourCycle]].
+ // 33. If hc is null, then
+ // a. Set hc to hcDefault.
+ auto hour_cycle_value = date_time_format.has_hour_cycle() ? date_time_format.hour_cycle() : *default_hour_cycle;
+
+ // 34. If hour12 is true, then
+ if (hour12.is_boolean() && hour12.as_bool()) {
+ // a. If hcDefault is "h11" or "h23", then
+ if ((default_hour_cycle == Unicode::HourCycle::H11) || (default_hour_cycle == Unicode::HourCycle::H23)) {
+ // i. Set hc to "h11".
+ hour_cycle_value = Unicode::HourCycle::H11;
+ }
+ // b. Else,
+ else {
+ // i. Set hc to "h12".
+ hour_cycle_value = Unicode::HourCycle::H12;
+ }
+ }
+ // 35. Else if hour12 is false, then
+ else if (hour12.is_boolean() && !hour12.as_bool()) {
+ // a. If hcDefault is "h11" or "h23", then
+ if ((default_hour_cycle == Unicode::HourCycle::H11) || (default_hour_cycle == Unicode::HourCycle::H23)) {
+ // i. Set hc to "h23".
+ hour_cycle_value = Unicode::HourCycle::H23;
+ }
+ // b. Else,
+ else {
+ // i. Set hc to "h24".
+ hour_cycle_value = Unicode::HourCycle::H24;
+ }
+ }
+ // 36. Else,
+ else {
+ // a. Assert: hour12 is undefined.
+ VERIFY(hour12.is_undefined());
+ }
+
+ // 37. Set dateTimeFormat.[[HourCycle]] to hc.
+ date_time_format.set_hour_cycle(hour_cycle_value);
+
+ // 38. Set formatOptions.[[hourCycle]] to hc.
+ format_options.hour_cycle = hour_cycle_value;
+
+ // 39. Let matcher be ? GetOption(options, "formatMatcher", "string", « "basic", "best fit" », "best fit").
matcher = TRY(get_option(global_object, *options, vm.names.formatMatcher, Value::Type::String, AK::Array { "basic"sv, "best fit"sv }, "best fit"sv));
- // 32. Let dateStyle be ? GetOption(options, "dateStyle", "string", « "full", "long", "medium", "short" », undefined).
+ // 40. Let dateStyle be ? GetOption(options, "dateStyle", "string", « "full", "long", "medium", "short" », undefined).
auto date_style = TRY(get_option(global_object, *options, vm.names.dateStyle, Value::Type::String, AK::Array { "full"sv, "long"sv, "medium"sv, "short"sv }, Empty {}));
- // 33. Set dateTimeFormat.[[DateStyle]] to dateStyle.
+ // 41. Set dateTimeFormat.[[DateStyle]] to dateStyle.
if (!date_style.is_undefined())
date_time_format.set_date_style(date_style.as_string().string());
- // 34. Let timeStyle be ? GetOption(options, "timeStyle", "string", « "full", "long", "medium", "short" », undefined).
+ // 42. Let timeStyle be ? GetOption(options, "timeStyle", "string", « "full", "long", "medium", "short" », undefined).
auto time_style = TRY(get_option(global_object, *options, vm.names.timeStyle, Value::Type::String, AK::Array { "full"sv, "long"sv, "medium"sv, "short"sv }, Empty {}));
- // 35. Set dateTimeFormat.[[TimeStyle]] to timeStyle.
+ // 43. Set dateTimeFormat.[[TimeStyle]] to timeStyle.
if (!time_style.is_undefined())
date_time_format.set_time_style(time_style.as_string().string());
Optional<Unicode::CalendarPattern> best_format {};
- // 36. If dateStyle is not undefined or timeStyle is not undefined, then
+ // 44. If dateStyle is not undefined or timeStyle is not undefined, then
if (date_time_format.has_date_style() || date_time_format.has_time_style()) {
// a. For each row in Table 4, except the header row, do
TRY(for_each_calendar_field(global_object, format_options, [&](auto const& option, auto const& property, auto const&) -> ThrowCompletionOr<void> {
// i. Let prop be the name given in the Property column of the row.
- // ii. Let p be opt.[[<prop>]].
+ // ii. Let p be formatOptions.[[<prop>]].
// iii. If p is not undefined, then
if (option.has_value()) {
// 1. Throw a TypeError exception.
@@ -250,28 +300,24 @@ ThrowCompletionOr<DateTimeFormat*> initialize_date_time_format(GlobalObject& glo
// c. Let bestFormat be DateTimeStyleFormat(dateStyle, timeStyle, styles).
best_format = date_time_style_format(data_locale, date_time_format);
}
- // 37. Else,
+ // 45. Else,
else {
// a. Let formats be dataLocaleData.[[formats]].[[<calendar>]].
auto formats = Unicode::get_calendar_available_formats(data_locale, date_time_format.calendar());
// b. If matcher is "basic", then
if (matcher.as_string().string() == "basic"sv) {
- // i. Let bestFormat be BasicFormatMatcher(opt, formats).
+ // i. Let bestFormat be BasicFormatMatcher(formatOptions, formats).
best_format = basic_format_matcher(format_options, move(formats));
}
// c. Else,
else {
- // i. Let bestFormat be BestFitFormatMatcher(opt, formats).
+ // i. Let bestFormat be BestFitFormatMatcher(formatOptions, formats).
best_format = best_fit_format_matcher(format_options, move(formats));
}
}
- // Non-standard, best_format will be empty if Unicode data generation is disabled.
- if (!best_format.has_value())
- return &date_time_format;
-
- // 38. For each row in Table 4, except the header row, in table order, do
+ // 46. For each row in Table 4, except the header row, in table order, do
date_time_format.for_each_calendar_field_zipped_with(*best_format, [&](auto& date_time_format_field, auto const& best_format_field, auto) {
// a. Let prop be the name given in the Property column of the row.
// b. If bestFormat has a field [[<prop>]], then
@@ -285,93 +331,42 @@ ThrowCompletionOr<DateTimeFormat*> initialize_date_time_format(GlobalObject& glo
String pattern;
Vector<Unicode::CalendarRangePattern> range_patterns;
- // 39. If dateTimeFormat.[[Hour]] is undefined, then
+ // 47. If dateTimeFormat.[[Hour]] is undefined, then
if (!date_time_format.has_hour()) {
// a. Set dateTimeFormat.[[HourCycle]] to undefined.
date_time_format.clear_hour_cycle();
+ }
- // b. Let pattern be bestFormat.[[pattern]].
- pattern = move(best_format->pattern);
+ // 48. If dateTimeformat.[[HourCycle]] is "h11" or "h12", then
+ if ((hour_cycle_value == Unicode::HourCycle::H11) || (hour_cycle_value == Unicode::HourCycle::H12)) {
+ // a. Let pattern be bestFormat.[[pattern12]].
+ if (best_format->pattern12.has_value()) {
+ pattern = best_format->pattern12.release_value();
+ } else {
+ // Non-standard, LibUnicode only provides [[pattern12]] when [[pattern]] has a day
+ // period. Other implementations provide [[pattern12]] as a copy of [[pattern]].
+ pattern = move(best_format->pattern);
+ }
- // c. Let rangePatterns be bestFormat.[[rangePatterns]].
- range_patterns = Unicode::get_calendar_range_formats(data_locale, date_time_format.calendar(), best_format->skeleton);
+ // b. Let rangePatterns be bestFormat.[[rangePatterns12]].
+ range_patterns = Unicode::get_calendar_range12_formats(data_locale, date_time_format.calendar(), best_format->skeleton);
}
- // 40. Else,
+ // 49. Else,
else {
- // a. Let hcDefault be dataLocaleData.[[hourCycle]].
- auto default_hour_cycle = Unicode::get_default_regional_hour_cycle(data_locale);
- VERIFY(default_hour_cycle.has_value());
-
- // b. Let hc be dateTimeFormat.[[HourCycle]].
- // c. If hc is null, then
- // i. Set hc to hcDefault.
- auto hour_cycle = date_time_format.has_hour_cycle() ? date_time_format.hour_cycle() : *default_hour_cycle;
-
- // d. If hour12 is not undefined, then
- if (!hour12.is_undefined()) {
- // i. If hour12 is true, then
- if (hour12.as_bool()) {
- // 1. If hcDefault is "h11" or "h23", then
- if ((default_hour_cycle == Unicode::HourCycle::H11) || (default_hour_cycle == Unicode::HourCycle::H23)) {
- // a. Set hc to "h11".
- hour_cycle = Unicode::HourCycle::H11;
- }
- // 2. Else,
- else {
- // a. Set hc to "h12".
- hour_cycle = Unicode::HourCycle::H12;
- }
- }
- // ii. Else,
- else {
- // 1. Assert: hour12 is false.
- // 2. If hcDefault is "h11" or "h23", then
- if ((default_hour_cycle == Unicode::HourCycle::H11) || (default_hour_cycle == Unicode::HourCycle::H23)) {
- // a. Set hc to "h23".
- hour_cycle = Unicode::HourCycle::H23;
- }
- // 3. Else,
- else {
- // a. Set hc to "h24".
- hour_cycle = Unicode::HourCycle::H24;
- }
- }
- }
-
- // e. Set dateTimeFormat.[[HourCycle]] to hc.
- date_time_format.set_hour_cycle(hour_cycle);
-
- // f. If dateTimeformat.[[HourCycle]] is "h11" or "h12", then
- if ((hour_cycle == Unicode::HourCycle::H11) || (hour_cycle == Unicode::HourCycle::H12)) {
- // i. Let pattern be bestFormat.[[pattern12]].
- if (best_format->pattern12.has_value()) {
- pattern = best_format->pattern12.release_value();
- } else {
- // Non-standard, LibUnicode only provides [[pattern12]] when [[pattern]] has a day
- // period. Other implementations provide [[pattern12]] as a copy of [[pattern]].
- pattern = move(best_format->pattern);
- }
-
- // ii. Let rangePatterns be bestFormat.[[rangePatterns12]].
- range_patterns = Unicode::get_calendar_range12_formats(data_locale, date_time_format.calendar(), best_format->skeleton);
- }
- // g. Else,
- else {
- // i. Let pattern be bestFormat.[[pattern]].
- pattern = move(best_format->pattern);
+ // a. Let pattern be bestFormat.[[pattern]].
+ pattern = move(best_format->pattern);
- // ii. Let rangePatterns be bestFormat.[[rangePatterns]].
- range_patterns = Unicode::get_calendar_range_formats(data_locale, date_time_format.calendar(), best_format->skeleton);
- }
+ // b. Let rangePatterns be bestFormat.[[rangePatterns]].
+ range_patterns = Unicode::get_calendar_range_formats(data_locale, date_time_format.calendar(), best_format->skeleton);
}
- // 41. Set dateTimeFormat.[[Pattern]] to pattern.
+ // 50. Set dateTimeFormat.[[Pattern]] to pattern.
date_time_format.set_pattern(move(pattern));
- // 42. Set dateTimeFormat.[[RangePatterns]] to rangePatterns.
+ // 51. Set dateTimeFormat.[[RangePatterns]] to rangePatterns.
date_time_format.set_range_patterns(move(range_patterns));
- // 43. Return dateTimeFormat.
+ // 52. Return dateTimeFormat.
return &date_time_format;
}