diff options
author | Timothy Flynn <trflynn89@pm.me> | 2022-01-10 08:02:01 -0500 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2022-01-10 16:18:05 +0100 |
commit | 05de9b82b871c3967e7c739c2d21db0621248ded (patch) | |
tree | 96820a5f7ec754ff9597643d94a1876f9c597ce0 | |
parent | 15947aa1f0e53c2aaa33c824b960751e47b7c23c (diff) | |
download | serenity-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.cpp | 177 |
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; } |