From 5bdee9e38a2ed404fe0b6b03a4c7f30560ba7b5f Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Fri, 10 Dec 2021 12:57:59 -0500 Subject: [PATCH] LibJS: Use locale-aware day period time ranges to format period symbols For the test cases changed here, we now recognize "morning2" and "afternoon2" from the CLDR, so the expected results now match the specs and other engines. --- .../LibJS/Runtime/Intl/DateTimeFormat.cpp | 19 +++---------------- .../DateTimeFormat.prototype.format.js | 8 +++----- .../DateTimeFormat.prototype.formatToParts.js | 4 +--- 3 files changed, 7 insertions(+), 24 deletions(-) diff --git a/Userland/Libraries/LibJS/Runtime/Intl/DateTimeFormat.cpp b/Userland/Libraries/LibJS/Runtime/Intl/DateTimeFormat.cpp index 4144976733..705388477b 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/DateTimeFormat.cpp +++ b/Userland/Libraries/LibJS/Runtime/Intl/DateTimeFormat.cpp @@ -755,19 +755,6 @@ static Optional find_calendar_field(StringView name, Unicode::Cal return {}; } -static Optional day_period_for_hour(StringView locale, StringView calendar, Unicode::CalendarPatternStyle style, u8 hour) -{ - // FIXME: This isn't locale-aware. We should parse the CLDR's cldr-core/supplemental/dayPeriods.json file - // to acquire day periods per-locale. For now, these are hard-coded to the en locale's values. - if ((hour >= 6) && (hour < 12)) - return Unicode::get_calendar_day_period_symbol(locale, calendar, style, Unicode::DayPeriod::Morning1); - if ((hour >= 12) && (hour < 18)) - return Unicode::get_calendar_day_period_symbol(locale, calendar, style, Unicode::DayPeriod::Afternoon1); - if ((hour >= 18) && (hour < 21)) - return Unicode::get_calendar_day_period_symbol(locale, calendar, style, Unicode::DayPeriod::Evening1); - return Unicode::get_calendar_day_period_symbol(locale, calendar, style, Unicode::DayPeriod::Night1); -} - // 11.1.7 FormatDateTimePattern ( dateTimeFormat, patternParts, x, rangeFormatOptions ), https://tc39.es/ecma402/#sec-formatdatetimepattern ThrowCompletionOr> format_date_time_pattern(GlobalObject& global_object, DateTimeFormat& date_time_format, Vector pattern_parts, Value time, Unicode::CalendarPattern const* range_format_options) { @@ -875,7 +862,7 @@ ThrowCompletionOr> format_date_time_pattern(GlobalObjec auto style = date_time_format.day_period(); // ii. Let fv be a String value representing the day period of tm in the form given by f; the String value depends upon the implementation and the effective locale of dateTimeFormat. - auto symbol = day_period_for_hour(data_locale, date_time_format.calendar(), style, local_time.hour); + auto symbol = Unicode::get_calendar_day_period_symbol_for_hour(data_locale, date_time_format.calendar(), style, local_time.hour); if (symbol.has_value()) formatted_value = *symbol; @@ -1236,10 +1223,10 @@ ThrowCompletionOr> partition_date_time_range_ // iii. Else if fieldName is equal to [[DayPeriod]], then case Unicode::CalendarRangePattern::Field::DayPeriod: { // 1. Let v1 be a String value representing the day period of tm1; the String value depends upon the implementation and the effective locale of dateTimeFormat. - auto start_period = day_period_for_hour(date_time_format.data_locale(), date_time_format.calendar(), Unicode::CalendarPatternStyle::Short, start_value); + auto start_period = Unicode::get_calendar_day_period_symbol_for_hour(date_time_format.data_locale(), date_time_format.calendar(), Unicode::CalendarPatternStyle::Short, start_value); // 2. Let v2 be a String value representing the day period of tm2; the String value depends upon the implementation and the effective locale of dateTimeFormat. - auto end_period = day_period_for_hour(date_time_format.data_locale(), date_time_format.calendar(), Unicode::CalendarPatternStyle::Short, end_value); + auto end_period = Unicode::get_calendar_day_period_symbol_for_hour(date_time_format.data_locale(), date_time_format.calendar(), Unicode::CalendarPatternStyle::Short, end_value); // 3. If v1 is not equal to v2, then if (start_period != end_period) { diff --git a/Userland/Libraries/LibJS/Tests/builtins/Intl/DateTimeFormat/DateTimeFormat.prototype.format.js b/Userland/Libraries/LibJS/Tests/builtins/Intl/DateTimeFormat/DateTimeFormat.prototype.format.js index b15db71704..368a6fd5e6 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/Intl/DateTimeFormat/DateTimeFormat.prototype.format.js +++ b/Userland/Libraries/LibJS/Tests/builtins/Intl/DateTimeFormat/DateTimeFormat.prototype.format.js @@ -228,12 +228,10 @@ describe("day", () => { describe("dayPeriod", () => { // prettier-ignore - // FIXME: The ar formats aren't entirely correct. LibUnicode is only parsing e.g. "morning1" in the "dayPeriods" - // CLDR object. It will need to parse "morning2", and figure out how to apply it. const data = [ - { dayPeriod: "narrow", en0: "5 in the afternoon", en1: "7 in the morning", ar0: "٥ ظهرًا", ar1: "٧ فجرًا" }, - { dayPeriod: "short", en0: "5 in the afternoon", en1: "7 in the morning", ar0: "٥ ظهرًا", ar1: "٧ فجرًا" }, - { dayPeriod: "long", en0: "5 in the afternoon", en1: "7 in the morning", ar0: "٥ ظهرًا", ar1: "٧ في الصباح" }, + { dayPeriod: "narrow", en0: "5 in the afternoon", en1: "7 in the morning", ar0: "٥ بعد الظهر", ar1: "٧ صباحًا" }, + { dayPeriod: "short", en0: "5 in the afternoon", en1: "7 in the morning", ar0: "٥ بعد الظهر", ar1: "٧ ص" }, + { dayPeriod: "long", en0: "5 in the afternoon", en1: "7 in the morning", ar0: "٥ بعد الظهر", ar1: "٧ صباحًا" }, ]; test("all", () => { diff --git a/Userland/Libraries/LibJS/Tests/builtins/Intl/DateTimeFormat/DateTimeFormat.prototype.formatToParts.js b/Userland/Libraries/LibJS/Tests/builtins/Intl/DateTimeFormat/DateTimeFormat.prototype.formatToParts.js index 10cee14628..e77bc6d62d 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/Intl/DateTimeFormat/DateTimeFormat.prototype.formatToParts.js +++ b/Userland/Libraries/LibJS/Tests/builtins/Intl/DateTimeFormat/DateTimeFormat.prototype.formatToParts.js @@ -233,8 +233,6 @@ describe("special cases", () => { { type: "dayPeriod", value: "in the morning" }, ]); - // FIXME: The ar format isn't entirely correct. LibUnicode is only parsing e.g. "morning1" in the "dayPeriods" - // CLDR object. It will need to parse "morning2", and figure out how to apply it. const ar = new Intl.DateTimeFormat("ar", { dayPeriod: "long", hour: "numeric", @@ -243,7 +241,7 @@ describe("special cases", () => { expect(ar.formatToParts(d)).toEqual([ { type: "hour", value: "٧" }, { type: "literal", value: " " }, - { type: "dayPeriod", value: "في الصباح" }, + { type: "dayPeriod", value: "صباحًا" }, ]); });