1
0
mirror of https://github.com/SerenityOS/serenity synced 2024-07-09 06:40:45 +00:00

LibLocale+LibJS+ClockSettings: Make date time format APIs infallible

These APIs only perform small allocations, and are only used by LibJS
and the time zone settings widget. Callers which could only have failed
from these APIs are also made to be infallible here.
This commit is contained in:
Timothy Flynn 2023-08-22 16:41:36 -04:00 committed by Andreas Kling
parent 0914e86691
commit 7536648498
9 changed files with 183 additions and 191 deletions

View File

@ -1793,13 +1793,13 @@ static void convert_calendar_fields(SourceType const& source, TargetType& target
}
struct CalendarPatternImpl {
ErrorOr<CalendarPattern> to_unicode_calendar_pattern() const {
CalendarPattern to_unicode_calendar_pattern() const {
CalendarPattern calendar_pattern {};
calendar_pattern.skeleton = TRY(String::from_utf8(decode_string(skeleton)));
calendar_pattern.pattern = TRY(String::from_utf8(decode_string(pattern)));
calendar_pattern.skeleton = MUST(String::from_utf8(decode_string(skeleton)));
calendar_pattern.pattern = MUST(String::from_utf8(decode_string(pattern)));
if (pattern12 != 0)
calendar_pattern.pattern12 = TRY(String::from_utf8(decode_string(pattern12)));
calendar_pattern.pattern12 = MUST(String::from_utf8(decode_string(pattern12)));
convert_calendar_fields(*this, calendar_pattern);
return calendar_pattern;
@ -1823,14 +1823,14 @@ struct CalendarPatternImpl {
};
struct CalendarRangePatternImpl {
ErrorOr<CalendarRangePattern> to_unicode_calendar_range_pattern() const {
CalendarRangePattern to_unicode_calendar_range_pattern() const {
CalendarRangePattern calendar_range_pattern {};
if (field != -1)
calendar_range_pattern.field = static_cast<CalendarRangePattern::Field>(field);
calendar_range_pattern.start_range = TRY(String::from_utf8(decode_string(start_range)));
calendar_range_pattern.start_range = MUST(String::from_utf8(decode_string(start_range)));
calendar_range_pattern.separator = decode_string(separator);
calendar_range_pattern.end_range = TRY(String::from_utf8(decode_string(end_range)));
calendar_range_pattern.end_range = MUST(String::from_utf8(decode_string(end_range)));
convert_calendar_fields(*this, calendar_range_pattern);
return calendar_range_pattern;
@ -1863,13 +1863,13 @@ struct CalendarRangePatternImpl {
generator.append(R"~~~(
struct CalendarFormatImpl {
ErrorOr<CalendarFormat> to_unicode_calendar_format() const {
CalendarFormat to_unicode_calendar_format() const {
CalendarFormat calendar_format {};
calendar_format.full_format = TRY(s_calendar_patterns[full_format].to_unicode_calendar_pattern());
calendar_format.long_format = TRY(s_calendar_patterns[long_format].to_unicode_calendar_pattern());
calendar_format.medium_format = TRY(s_calendar_patterns[medium_format].to_unicode_calendar_pattern());
calendar_format.short_format = TRY(s_calendar_patterns[short_format].to_unicode_calendar_pattern());
calendar_format.full_format = s_calendar_patterns[full_format].to_unicode_calendar_pattern();
calendar_format.long_format = s_calendar_patterns[long_format].to_unicode_calendar_pattern();
calendar_format.medium_format = s_calendar_patterns[medium_format].to_unicode_calendar_pattern();
calendar_format.short_format = s_calendar_patterns[short_format].to_unicode_calendar_pattern();
return calendar_format;
}
@ -2045,11 +2045,11 @@ static Optional<Calendar> keyword_to_calendar(KeywordCalendar keyword)
}
}
ErrorOr<Vector<HourCycle>> get_regional_hour_cycles(StringView region)
Vector<HourCycle> get_regional_hour_cycles(StringView region)
{
auto region_value = hour_cycle_region_from_string(region);
if (!region_value.has_value())
return Vector<HourCycle> {};
return {};
auto region_index = to_underlying(*region_value);
@ -2057,7 +2057,7 @@ ErrorOr<Vector<HourCycle>> get_regional_hour_cycles(StringView region)
auto const& regional_hour_cycles = s_hour_cycle_lists.at(regional_hour_cycles_index);
Vector<HourCycle> hour_cycles;
TRY(hour_cycles.try_ensure_capacity(regional_hour_cycles.size()));
hour_cycles.ensure_capacity(regional_hour_cycles.size());
for (auto hour_cycle : regional_hour_cycles)
hour_cycles.unchecked_append(static_cast<HourCycle>(hour_cycle));
@ -2125,59 +2125,59 @@ static CalendarData const* find_calendar_data(StringView locale, StringView cale
return lookup_calendar(*default_calendar);
}
ErrorOr<Optional<CalendarFormat>> get_calendar_date_format(StringView locale, StringView calendar)
Optional<CalendarFormat> get_calendar_date_format(StringView locale, StringView calendar)
{
if (auto const* data = find_calendar_data(locale, calendar); data != nullptr) {
auto const& formats = s_calendar_formats.at(data->date_formats);
return TRY(formats.to_unicode_calendar_format());
return formats.to_unicode_calendar_format();
}
return OptionalNone {};
return {};
}
ErrorOr<Optional<CalendarFormat>> get_calendar_time_format(StringView locale, StringView calendar)
Optional<CalendarFormat> get_calendar_time_format(StringView locale, StringView calendar)
{
if (auto const* data = find_calendar_data(locale, calendar); data != nullptr) {
auto const& formats = s_calendar_formats.at(data->time_formats);
return TRY(formats.to_unicode_calendar_format());
return formats.to_unicode_calendar_format();
}
return OptionalNone {};
return {};
}
ErrorOr<Optional<CalendarFormat>> get_calendar_date_time_format(StringView locale, StringView calendar)
Optional<CalendarFormat> get_calendar_date_time_format(StringView locale, StringView calendar)
{
if (auto const* data = find_calendar_data(locale, calendar); data != nullptr) {
auto const& formats = s_calendar_formats.at(data->date_time_formats);
return TRY(formats.to_unicode_calendar_format());
return formats.to_unicode_calendar_format();
}
return OptionalNone {};
return {};
}
ErrorOr<Vector<CalendarPattern>> get_calendar_available_formats(StringView locale, StringView calendar)
Vector<CalendarPattern> get_calendar_available_formats(StringView locale, StringView calendar)
{
Vector<CalendarPattern> result {};
if (auto const* data = find_calendar_data(locale, calendar); data != nullptr) {
auto const& available_formats = s_calendar_pattern_lists.at(data->available_formats);
TRY(result.try_ensure_capacity(available_formats.size()));
result.ensure_capacity(available_formats.size());
for (auto const& format : available_formats)
result.unchecked_append(TRY(s_calendar_patterns[format].to_unicode_calendar_pattern()));
result.unchecked_append(s_calendar_patterns[format].to_unicode_calendar_pattern());
}
return result;
}
ErrorOr<Optional<CalendarRangePattern>> get_calendar_default_range_format(StringView locale, StringView calendar)
Optional<CalendarRangePattern> get_calendar_default_range_format(StringView locale, StringView calendar)
{
if (auto const* data = find_calendar_data(locale, calendar); data != nullptr) {
auto const& pattern = s_calendar_range_patterns[data->default_range_format];
return TRY(pattern.to_unicode_calendar_range_pattern());
return pattern.to_unicode_calendar_range_pattern();
}
return OptionalNone {};
return {};
}
ErrorOr<Vector<CalendarRangePattern>> get_calendar_range_formats(StringView locale, StringView calendar, StringView skeleton)
Vector<CalendarRangePattern> get_calendar_range_formats(StringView locale, StringView calendar, StringView skeleton)
{
Vector<CalendarRangePattern> result {};
@ -2188,14 +2188,14 @@ ErrorOr<Vector<CalendarRangePattern>> get_calendar_range_formats(StringView loca
auto const& pattern = s_calendar_range_patterns[format];
if (skeleton == decode_string(pattern.skeleton))
TRY(result.try_append(TRY(pattern.to_unicode_calendar_range_pattern())));
result.append(pattern.to_unicode_calendar_range_pattern());
}
}
return result;
}
ErrorOr<Vector<CalendarRangePattern>> get_calendar_range12_formats(StringView locale, StringView calendar, StringView skeleton)
Vector<CalendarRangePattern> get_calendar_range12_formats(StringView locale, StringView calendar, StringView skeleton)
{
Vector<CalendarRangePattern> result {};
@ -2206,14 +2206,14 @@ ErrorOr<Vector<CalendarRangePattern>> get_calendar_range12_formats(StringView lo
auto const& pattern = s_calendar_range_patterns[format];
if (skeleton == decode_string(pattern.skeleton))
TRY(result.try_append(TRY(pattern.to_unicode_calendar_range_pattern())));
result.append(pattern.to_unicode_calendar_range_pattern());
}
}
return result;
}
static ErrorOr<ReadonlySpan<@string_index_type@>> find_calendar_symbols(StringView locale, StringView calendar, CalendarSymbol symbol, CalendarPatternStyle style)
static ReadonlySpan<@string_index_type@> find_calendar_symbols(StringView locale, StringView calendar, CalendarSymbol symbol, CalendarPatternStyle style)
{
if (auto const* data = find_calendar_data(locale, calendar); data != nullptr) {
auto const& symbols_list = s_calendar_symbol_lists[data->symbols];
@ -2241,62 +2241,62 @@ static ErrorOr<ReadonlySpan<@string_index_type@>> find_calendar_symbols(StringVi
return s_symbol_lists.at(symbol_list_index);
}
return ReadonlySpan<@string_index_type@> {};
return {};
}
ErrorOr<Optional<StringView>> get_calendar_era_symbol(StringView locale, StringView calendar, CalendarPatternStyle style, Era value)
Optional<StringView> get_calendar_era_symbol(StringView locale, StringView calendar, CalendarPatternStyle style, Era value)
{
auto symbols = TRY(find_calendar_symbols(locale, calendar, CalendarSymbol::Era, style));
auto symbols = find_calendar_symbols(locale, calendar, CalendarSymbol::Era, style);
if (auto value_index = to_underlying(value); value_index < symbols.size()) {
if (auto symbol_index = symbols.at(value_index); symbol_index != 0)
return Optional<StringView> { decode_string(symbol_index) };
return decode_string(symbol_index);
}
return OptionalNone {};
return {};
}
ErrorOr<Optional<StringView>> get_calendar_month_symbol(StringView locale, StringView calendar, CalendarPatternStyle style, Month value)
Optional<StringView> get_calendar_month_symbol(StringView locale, StringView calendar, CalendarPatternStyle style, Month value)
{
auto symbols = TRY(find_calendar_symbols(locale, calendar, CalendarSymbol::Month, style));
auto symbols = find_calendar_symbols(locale, calendar, CalendarSymbol::Month, style);
if (auto value_index = to_underlying(value); value_index < symbols.size()) {
if (auto symbol_index = symbols.at(value_index); symbol_index != 0)
return Optional<StringView> { decode_string(symbol_index) };
return decode_string(symbol_index);
}
return OptionalNone {};
return {};
}
ErrorOr<Optional<StringView>> get_calendar_weekday_symbol(StringView locale, StringView calendar, CalendarPatternStyle style, Weekday value)
Optional<StringView> get_calendar_weekday_symbol(StringView locale, StringView calendar, CalendarPatternStyle style, Weekday value)
{
auto symbols = TRY(find_calendar_symbols(locale, calendar, CalendarSymbol::Weekday, style));
auto symbols = find_calendar_symbols(locale, calendar, CalendarSymbol::Weekday, style);
if (auto value_index = to_underlying(value); value_index < symbols.size()) {
if (auto symbol_index = symbols.at(value_index); symbol_index != 0)
return Optional<StringView> { decode_string(symbol_index) };
return decode_string(symbol_index);
}
return OptionalNone {};
return {};
}
ErrorOr<Optional<StringView>> get_calendar_day_period_symbol(StringView locale, StringView calendar, CalendarPatternStyle style, DayPeriod value)
Optional<StringView> get_calendar_day_period_symbol(StringView locale, StringView calendar, CalendarPatternStyle style, DayPeriod value)
{
auto symbols = TRY(find_calendar_symbols(locale, calendar, CalendarSymbol::DayPeriod, style));
auto symbols = find_calendar_symbols(locale, calendar, CalendarSymbol::DayPeriod, style);
if (auto value_index = to_underlying(value); value_index < symbols.size()) {
if (auto symbol_index = symbols.at(value_index); symbol_index != 0)
return Optional<StringView> { decode_string(symbol_index) };
return decode_string(symbol_index);
}
return OptionalNone {};
return {};
}
ErrorOr<Optional<StringView>> get_calendar_day_period_symbol_for_hour(StringView locale, StringView calendar, CalendarPatternStyle style, u8 hour)
Optional<StringView> get_calendar_day_period_symbol_for_hour(StringView locale, StringView calendar, CalendarPatternStyle style, u8 hour)
{
auto locale_value = locale_from_string(locale);
if (!locale_value.has_value())
return OptionalNone {};
return {};
auto locale_index = to_underlying(*locale_value) - 1; // Subtract 1 because 0 == Locale::None.

View File

@ -1680,7 +1680,7 @@ Optional<StringView> get_preferred_keyword_value_for_locale(StringView locale, S
// FIXME: Calendar keywords are also region-based, and will need to be handled here when we support non-Gregorian calendars:
// https://github.com/unicode-org/cldr-json/blob/main/cldr-json/cldr-core/supplemental/calendarPreferenceData.json
if (key == "hc"sv) {
auto hour_cycles = MUST(get_locale_hour_cycles(locale));
auto hour_cycles = get_locale_hour_cycles(locale);
if (hour_cycles.is_empty())
return OptionalNone {};
@ -1709,7 +1709,7 @@ Vector<StringView> get_keywords_for_locale(StringView locale, StringView key)
// FIXME: Calendar keywords are also region-based, and will need to be handled here when we support non-Gregorian calendars:
// https://github.com/unicode-org/cldr-json/blob/main/cldr-json/cldr-core/supplemental/calendarPreferenceData.json
if (key == "hc"sv) {
auto hour_cycles = MUST(get_locale_hour_cycles(locale));
auto hour_cycles = get_locale_hour_cycles(locale);
Vector<StringView> values;
values.ensure_capacity(hour_cycles.size());

View File

@ -75,7 +75,7 @@ TEST_CASE(time_zone_name)
constexpr auto jan_1_2022 = AK::UnixDateTime::from_seconds_since_epoch(1640995200); // Saturday, January 1, 2022 12:00:00 AM
for (auto const& test : test_data) {
auto time_zone = MUST(Locale::format_time_zone(test.locale, test.time_zone, test.style, jan_1_2022));
auto time_zone = Locale::format_time_zone(test.locale, test.time_zone, test.style, jan_1_2022);
EXPECT_EQ(time_zone, test.expected_result);
}
}
@ -125,7 +125,7 @@ TEST_CASE(time_zone_name_dst)
constexpr auto sep_19_2022 = AK::UnixDateTime::from_seconds_since_epoch(1663553728); // Monday, September 19, 2022 2:15:28 AM
for (auto const& test : test_data) {
auto time_zone = MUST(Locale::format_time_zone(test.locale, test.time_zone, test.style, sep_19_2022));
auto time_zone = Locale::format_time_zone(test.locale, test.time_zone, test.style, sep_19_2022);
EXPECT_EQ(time_zone, test.expected_result);
}
}
@ -182,7 +182,7 @@ TEST_CASE(format_time_zone_offset)
};
for (auto const& test : test_data) {
auto time_zone = MUST(Locale::format_time_zone(test.locale, test.time_zone, test.style, test.time));
auto time_zone = Locale::format_time_zone(test.locale, test.time_zone, test.style, test.time);
EXPECT_EQ(time_zone, test.expected_result);
}
}

View File

@ -135,8 +135,8 @@ void TimeZoneSettingsWidget::set_time_zone_location()
auto locale = Locale::default_locale();
auto now = AK::UnixDateTime::now();
auto name = Locale::format_time_zone(locale, m_time_zone, Locale::CalendarPatternStyle::Long, now).release_value_but_fixme_should_propagate_errors();
auto offset = Locale::format_time_zone(locale, m_time_zone, Locale::CalendarPatternStyle::LongOffset, now).release_value_but_fixme_should_propagate_errors();
auto name = Locale::format_time_zone(locale, m_time_zone, Locale::CalendarPatternStyle::Long, now);
auto offset = Locale::format_time_zone(locale, m_time_zone, Locale::CalendarPatternStyle::LongOffset, now);
m_time_zone_text = DeprecatedString::formatted("{}\n({})", name, offset);
}

View File

@ -73,8 +73,8 @@ ThrowCompletionOr<Optional<::Locale::CalendarPattern>> date_time_style_format(VM
::Locale::CalendarPattern time_format {};
::Locale::CalendarPattern date_format {};
auto get_pattern = [&](auto type, auto style) -> ThrowCompletionOr<Optional<::Locale::CalendarPattern>> {
auto formats = TRY_OR_THROW_OOM(vm, ::Locale::get_calendar_format(data_locale, date_time_format.calendar(), type));
auto get_pattern = [&](auto type, auto style) -> Optional<::Locale::CalendarPattern> {
auto formats = ::Locale::get_calendar_format(data_locale, date_time_format.calendar(), type);
if (formats.has_value()) {
switch (style) {
@ -89,14 +89,14 @@ ThrowCompletionOr<Optional<::Locale::CalendarPattern>> date_time_style_format(VM
}
}
return OptionalNone {};
return {};
};
// 1. If timeStyle is not undefined, then
if (date_time_format.has_time_style()) {
// a. Assert: timeStyle is one of "full", "long", "medium", or "short".
// b. Let timeFormat be styles.[[TimeFormat]].[[<timeStyle>]].
auto pattern = MUST_OR_THROW_OOM(get_pattern(::Locale::CalendarFormatType::Time, date_time_format.time_style()));
auto pattern = get_pattern(::Locale::CalendarFormatType::Time, date_time_format.time_style());
if (!pattern.has_value())
return OptionalNone {};
@ -107,7 +107,7 @@ ThrowCompletionOr<Optional<::Locale::CalendarPattern>> date_time_style_format(VM
if (date_time_format.has_date_style()) {
// a. Assert: dateStyle is one of "full", "long", "medium", or "short".
// b. Let dateFormat be styles.[[DateFormat]].[[<dateStyle>]].
auto pattern = MUST_OR_THROW_OOM(get_pattern(::Locale::CalendarFormatType::Date, date_time_format.date_style()));
auto pattern = get_pattern(::Locale::CalendarFormatType::Date, date_time_format.date_style());
if (!pattern.has_value())
return OptionalNone {};
@ -131,7 +131,7 @@ ThrowCompletionOr<Optional<::Locale::CalendarPattern>> date_time_style_format(VM
});
// d. Let connector be styles.[[DateTimeFormat]].[[<dateStyle>]].
auto connector = MUST_OR_THROW_OOM(get_pattern(::Locale::CalendarFormatType::DateTime, date_time_format.date_style()));
auto connector = get_pattern(::Locale::CalendarFormatType::DateTime, date_time_format.date_style());
if (!connector.has_value())
return OptionalNone {};
@ -155,7 +155,7 @@ ThrowCompletionOr<Optional<::Locale::CalendarPattern>> date_time_style_format(VM
// NOTE: Our implementation of steps h-j differ from the spec. LibUnicode does not attach range patterns to the
// format pattern; rather, lookups for range patterns are performed separately based on the format pattern's
// skeleton. So we form a new skeleton here and defer the range pattern lookups.
format.skeleton = TRY_OR_THROW_OOM(vm, ::Locale::combine_skeletons(date_format.skeleton, time_format.skeleton));
format.skeleton = ::Locale::combine_skeletons(date_format.skeleton, time_format.skeleton);
// k. Return format.
return format;
@ -424,7 +424,7 @@ static Optional<StyleAndValue> find_calendar_field(StringView name, ::Locale::Ca
return {};
}
static ThrowCompletionOr<Optional<StringView>> resolve_day_period(VM& vm, StringView locale, StringView calendar, ::Locale::CalendarPatternStyle style, ReadonlySpan<PatternPartition> pattern_parts, LocalTime local_time)
static Optional<StringView> resolve_day_period(StringView locale, StringView calendar, ::Locale::CalendarPatternStyle style, ReadonlySpan<PatternPartition> pattern_parts, LocalTime local_time)
{
// Use the "noon" day period if the locale has it, but only if the time is either exactly 12:00.00 or would be displayed as such.
if (local_time.hour == 12) {
@ -439,13 +439,13 @@ static ThrowCompletionOr<Optional<StringView>> resolve_day_period(VM& vm, String
});
if (it == pattern_parts.end()) {
auto noon_symbol = TRY_OR_THROW_OOM(vm, ::Locale::get_calendar_day_period_symbol(locale, calendar, style, ::Locale::DayPeriod::Noon));
auto noon_symbol = ::Locale::get_calendar_day_period_symbol(locale, calendar, style, ::Locale::DayPeriod::Noon);
if (noon_symbol.has_value())
return *noon_symbol;
}
}
return TRY_OR_THROW_OOM(vm, ::Locale::get_calendar_day_period_symbol_for_hour(locale, calendar, style, local_time.hour));
return ::Locale::get_calendar_day_period_symbol_for_hour(locale, calendar, style, local_time.hour);
}
// 11.5.5 FormatDateTimePattern ( dateTimeFormat, patternParts, x, rangeFormatOptions ), https://tc39.es/ecma402/#sec-formatdatetimepattern
@ -552,7 +552,7 @@ ThrowCompletionOr<Vector<PatternPartition>> format_date_time_pattern(VM& vm, Dat
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 = MUST_OR_THROW_OOM(resolve_day_period(vm, data_locale, date_time_format.calendar(), style, pattern_parts, local_time));
auto symbol = resolve_day_period(data_locale, date_time_format.calendar(), style, pattern_parts, local_time);
if (symbol.has_value())
formatted_value = TRY_OR_THROW_OOM(vm, String::from_utf8(*symbol));
@ -571,7 +571,7 @@ ThrowCompletionOr<Vector<PatternPartition>> format_date_time_pattern(VM& vm, Dat
// iii. Let fv be a String value representing v in the form given by f; the String value depends upon the implementation and the effective locale of dateTimeFormat.
// The String value may also depend on the value of the [[InDST]] field of tm if f is "short", "long", "shortOffset", or "longOffset".
// If the implementation does not have a localized representation of f, then use the String value of v itself.
auto formatted_value = TRY_OR_THROW_OOM(vm, ::Locale::format_time_zone(data_locale, value, style, local_time.time_since_epoch()));
auto formatted_value = ::Locale::format_time_zone(data_locale, value, style, local_time.time_since_epoch());
// iv. Append a new Record { [[Type]]: p, [[Value]]: fv } as the last element of the list result.
TRY_OR_THROW_OOM(vm, result.try_append({ "timeZoneName"sv, move(formatted_value) }));
@ -652,11 +652,11 @@ ThrowCompletionOr<Vector<PatternPartition>> format_date_time_pattern(VM& vm, Dat
Optional<StringView> symbol;
if (part == "era"sv)
symbol = TRY_OR_THROW_OOM(vm, ::Locale::get_calendar_era_symbol(data_locale, date_time_format.calendar(), style, static_cast<::Locale::Era>(value)));
symbol = ::Locale::get_calendar_era_symbol(data_locale, date_time_format.calendar(), style, static_cast<::Locale::Era>(value));
else if (part == "month"sv)
symbol = TRY_OR_THROW_OOM(vm, ::Locale::get_calendar_month_symbol(data_locale, date_time_format.calendar(), style, static_cast<::Locale::Month>(value - 1)));
symbol = ::Locale::get_calendar_month_symbol(data_locale, date_time_format.calendar(), style, static_cast<::Locale::Month>(value - 1));
else if (part == "weekday"sv)
symbol = TRY_OR_THROW_OOM(vm, ::Locale::get_calendar_weekday_symbol(data_locale, date_time_format.calendar(), style, static_cast<::Locale::Weekday>(value)));
symbol = ::Locale::get_calendar_weekday_symbol(data_locale, date_time_format.calendar(), style, static_cast<::Locale::Weekday>(value));
if (symbol.has_value())
formatted_value = TRY_OR_THROW_OOM(vm, String::from_utf8(*symbol));
@ -684,13 +684,13 @@ ThrowCompletionOr<Vector<PatternPartition>> format_date_time_pattern(VM& vm, Dat
// ii. If v is greater than 11, then
if (value > 11) {
// 1. Let fv be an implementation and locale dependent String value representing "post meridiem".
auto symbol = TRY_OR_THROW_OOM(vm, ::Locale::get_calendar_day_period_symbol(data_locale, date_time_format.calendar(), ::Locale::CalendarPatternStyle::Short, ::Locale::DayPeriod::PM));
auto symbol = ::Locale::get_calendar_day_period_symbol(data_locale, date_time_format.calendar(), ::Locale::CalendarPatternStyle::Short, ::Locale::DayPeriod::PM);
formatted_value = TRY_OR_THROW_OOM(vm, String::from_utf8(symbol.value_or("PM"sv)));
}
// iii. Else,
else {
// 1. Let fv be an implementation and locale dependent String value representing "ante meridiem".
auto symbol = TRY_OR_THROW_OOM(vm, ::Locale::get_calendar_day_period_symbol(data_locale, date_time_format.calendar(), ::Locale::CalendarPatternStyle::Short, ::Locale::DayPeriod::AM));
auto symbol = ::Locale::get_calendar_day_period_symbol(data_locale, date_time_format.calendar(), ::Locale::CalendarPatternStyle::Short, ::Locale::DayPeriod::AM);
formatted_value = TRY_OR_THROW_OOM(vm, String::from_utf8(symbol.value_or("AM"sv)));
}
@ -806,30 +806,29 @@ ThrowCompletionOr<Array*> format_date_time_to_parts(VM& vm, DateTimeFormat& date
}
template<typename Callback>
ThrowCompletionOr<void> for_each_range_pattern_field(LocalTime const& time1, LocalTime const& time2, Callback&& callback)
void for_each_range_pattern_field(LocalTime const& time1, LocalTime const& time2, Callback&& callback)
{
// Table 4: Range pattern fields, https://tc39.es/ecma402/#table-datetimeformat-rangepatternfields
if (TRY(callback(static_cast<u8>(time1.era), static_cast<u8>(time2.era), ::Locale::CalendarRangePattern::Field::Era)) == IterationDecision::Break)
return {};
if (TRY(callback(time1.year, time2.year, ::Locale::CalendarRangePattern::Field::Year)) == IterationDecision::Break)
return {};
if (TRY(callback(time1.month, time2.month, ::Locale::CalendarRangePattern::Field::Month)) == IterationDecision::Break)
return {};
if (TRY(callback(time1.day, time2.day, ::Locale::CalendarRangePattern::Field::Day)) == IterationDecision::Break)
return {};
if (TRY(callback(time1.hour, time2.hour, ::Locale::CalendarRangePattern::Field::AmPm)) == IterationDecision::Break)
return {};
if (TRY(callback(time1.hour, time2.hour, ::Locale::CalendarRangePattern::Field::DayPeriod)) == IterationDecision::Break)
return {};
if (TRY(callback(time1.hour, time2.hour, ::Locale::CalendarRangePattern::Field::Hour)) == IterationDecision::Break)
return {};
if (TRY(callback(time1.minute, time2.minute, ::Locale::CalendarRangePattern::Field::Minute)) == IterationDecision::Break)
return {};
if (TRY(callback(time1.second, time2.second, ::Locale::CalendarRangePattern::Field::Second)) == IterationDecision::Break)
return {};
if (TRY(callback(time1.millisecond, time2.millisecond, ::Locale::CalendarRangePattern::Field::FractionalSecondDigits)) == IterationDecision::Break)
return {};
return {};
if (callback(static_cast<u8>(time1.era), static_cast<u8>(time2.era), ::Locale::CalendarRangePattern::Field::Era) == IterationDecision::Break)
return;
if (callback(time1.year, time2.year, ::Locale::CalendarRangePattern::Field::Year) == IterationDecision::Break)
return;
if (callback(time1.month, time2.month, ::Locale::CalendarRangePattern::Field::Month) == IterationDecision::Break)
return;
if (callback(time1.day, time2.day, ::Locale::CalendarRangePattern::Field::Day) == IterationDecision::Break)
return;
if (callback(time1.hour, time2.hour, ::Locale::CalendarRangePattern::Field::AmPm) == IterationDecision::Break)
return;
if (callback(time1.hour, time2.hour, ::Locale::CalendarRangePattern::Field::DayPeriod) == IterationDecision::Break)
return;
if (callback(time1.hour, time2.hour, ::Locale::CalendarRangePattern::Field::Hour) == IterationDecision::Break)
return;
if (callback(time1.minute, time2.minute, ::Locale::CalendarRangePattern::Field::Minute) == IterationDecision::Break)
return;
if (callback(time1.second, time2.second, ::Locale::CalendarRangePattern::Field::Second) == IterationDecision::Break)
return;
if (callback(time1.millisecond, time2.millisecond, ::Locale::CalendarRangePattern::Field::FractionalSecondDigits) == IterationDecision::Break)
return;
}
template<typename Callback>
@ -879,7 +878,7 @@ ThrowCompletionOr<Vector<PatternPartitionWithSource>> partition_date_time_range_
bool pattern_contains_larger_date_field = false;
// 11. While dateFieldsPracticallyEqual is true and patternContainsLargerDateField is false, repeat for each row of Table 4 in order, except the header row:
TRY(for_each_range_pattern_field(start_local_time, end_local_time, [&](auto start_value, auto end_value, auto field_name) -> ThrowCompletionOr<IterationDecision> {
for_each_range_pattern_field(start_local_time, end_local_time, [&](auto start_value, auto end_value, auto field_name) {
// a. Let fieldName be the name given in the Range Pattern Field column of the row.
// b. If rangePatterns has a field [[<fieldName>]], let rp be rangePatterns.[[<fieldName>]]; else let rp be undefined.
@ -918,10 +917,10 @@ ThrowCompletionOr<Vector<PatternPartitionWithSource>> partition_date_time_range_
// iii. Else if fieldName is equal to [[DayPeriod]], then
case ::Locale::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 = TRY_OR_THROW_OOM(vm, ::Locale::get_calendar_day_period_symbol_for_hour(date_time_format.data_locale(), date_time_format.calendar(), ::Locale::CalendarPatternStyle::Short, start_value));
auto start_period = ::Locale::get_calendar_day_period_symbol_for_hour(date_time_format.data_locale(), date_time_format.calendar(), ::Locale::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 = TRY_OR_THROW_OOM(vm, ::Locale::get_calendar_day_period_symbol_for_hour(date_time_format.data_locale(), date_time_format.calendar(), ::Locale::CalendarPatternStyle::Short, end_value));
auto end_period = ::Locale::get_calendar_day_period_symbol_for_hour(date_time_format.data_locale(), date_time_format.calendar(), ::Locale::CalendarPatternStyle::Short, end_value);
// 3. If v1 is not equal to v2, then
if (start_period != end_period) {
@ -981,7 +980,7 @@ ThrowCompletionOr<Vector<PatternPartitionWithSource>> partition_date_time_range_
if (date_fields_practically_equal && !pattern_contains_larger_date_field)
return IterationDecision::Continue;
return IterationDecision::Break;
}));
});
// 12. If dateFieldsPracticallyEqual is true, then
if (date_fields_practically_equal) {
@ -1011,7 +1010,7 @@ ThrowCompletionOr<Vector<PatternPartitionWithSource>> partition_date_time_range_
// 14. If rangePattern is undefined, then
if (!range_pattern.has_value()) {
// a. Let rangePattern be rangePatterns.[[Default]].
range_pattern = TRY_OR_THROW_OOM(vm, ::Locale::get_calendar_default_range_format(date_time_format.data_locale(), date_time_format.calendar()));
range_pattern = ::Locale::get_calendar_default_range_format(date_time_format.data_locale(), date_time_format.calendar());
// Non-standard, range_pattern will be empty if Unicode data generation is disabled.
if (!range_pattern.has_value())

View File

@ -166,7 +166,7 @@ ThrowCompletionOr<NonnullGCPtr<DateTimeFormat>> create_date_time_format(VM& vm,
// 24. Let dataLocaleData be localeData.[[<dataLocale>]].
// 25. Let hcDefault be dataLocaleData.[[hourCycle]].
auto default_hour_cycle = TRY_OR_THROW_OOM(vm, ::Locale::get_default_regional_hour_cycle(data_locale));
auto default_hour_cycle = ::Locale::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()) {
@ -394,7 +394,7 @@ ThrowCompletionOr<NonnullGCPtr<DateTimeFormat>> create_date_time_format(VM& vm,
}
// f. Let formats be dataLocaleData.[[formats]].[[<resolvedCalendar>]].
auto formats = TRY_OR_THROW_OOM(vm, ::Locale::get_calendar_available_formats(data_locale, date_time_format->calendar()));
auto formats = ::Locale::get_calendar_available_formats(data_locale, date_time_format->calendar());
// g. If matcher is "basic", then
if (matcher.as_string().utf8_string_view() == "basic"sv) {
@ -440,7 +440,7 @@ ThrowCompletionOr<NonnullGCPtr<DateTimeFormat>> create_date_time_format(VM& vm,
}
// b. Let rangePatterns be bestFormat.[[rangePatterns12]].
range_patterns = TRY_OR_THROW_OOM(vm, ::Locale::get_calendar_range12_formats(data_locale, date_time_format->calendar(), best_format->skeleton));
range_patterns = ::Locale::get_calendar_range12_formats(data_locale, date_time_format->calendar(), best_format->skeleton);
}
// 48. Else,
else {
@ -448,7 +448,7 @@ ThrowCompletionOr<NonnullGCPtr<DateTimeFormat>> create_date_time_format(VM& vm,
pattern = move(best_format->pattern);
// b. Let rangePatterns be bestFormat.[[rangePatterns]].
range_patterns = TRY_OR_THROW_OOM(vm, ::Locale::get_calendar_range_formats(data_locale, date_time_format->calendar(), best_format->skeleton));
range_patterns = ::Locale::get_calendar_range_formats(data_locale, date_time_format->calendar(), best_format->skeleton);
}
// 49. Set dateTimeFormat.[[Pattern]] to pattern.

View File

@ -208,8 +208,8 @@ static u8 weekday_to_integer(Optional<::Locale::Weekday> weekday, ::Locale::Week
static ThrowCompletionOr<Vector<u8>> weekend_of_locale(VM& vm, StringView locale)
{
auto weekend_start = weekday_to_integer(TRY_OR_THROW_OOM(vm, ::Locale::get_locale_weekend_start(locale)), ::Locale::Weekday::Saturday);
auto weekend_end = weekday_to_integer(TRY_OR_THROW_OOM(vm, ::Locale::get_locale_weekend_end(locale)), ::Locale::Weekday::Sunday);
auto weekend_start = weekday_to_integer(::Locale::get_locale_weekend_start(locale), ::Locale::Weekday::Saturday);
auto weekend_end = weekday_to_integer(::Locale::get_locale_weekend_end(locale), ::Locale::Weekday::Sunday);
// There currently aren't any regions in the CLDR which wrap around from Sunday (7) to Monday (1).
// If this changes, this logic will need to be updated to handle that.
@ -235,8 +235,8 @@ ThrowCompletionOr<WeekInfo> week_info_of_locale(VM& vm, Locale const& locale_obj
// 3. Return a record whose fields are defined by Table 1, with values based on locale.
WeekInfo week_info {};
week_info.minimal_days = TRY_OR_THROW_OOM(vm, ::Locale::get_locale_minimum_days(locale)).value_or(1);
week_info.first_day = weekday_to_integer(TRY_OR_THROW_OOM(vm, ::Locale::get_locale_first_day(locale)), ::Locale::Weekday::Monday);
week_info.minimal_days = ::Locale::get_locale_minimum_days(locale).value_or(1);
week_info.first_day = weekday_to_integer(::Locale::get_locale_first_day(locale), ::Locale::Weekday::Monday);
week_info.weekend = MUST_OR_THROW_OOM(weekend_of_locale(vm, locale));
return week_info;

View File

@ -92,10 +92,10 @@ StringView calendar_pattern_style_to_string(CalendarPatternStyle style)
}
Optional<HourCycleRegion> __attribute__((weak)) hour_cycle_region_from_string(StringView) { return {}; }
ErrorOr<Vector<HourCycle>> __attribute__((weak)) get_regional_hour_cycles(StringView) { return Vector<HourCycle> {}; }
Vector<HourCycle> __attribute__((weak)) get_regional_hour_cycles(StringView) { return {}; }
template<typename T, FallibleFunction<StringView> GetRegionalValues>
static ErrorOr<T> find_regional_values_for_locale(StringView locale, GetRegionalValues&& get_regional_values)
template<typename T, typename GetRegionalValues>
static T find_regional_values_for_locale(StringView locale, GetRegionalValues&& get_regional_values)
{
auto has_value = [](auto const& container) {
if constexpr (requires { container.has_value(); })
@ -104,7 +104,7 @@ static ErrorOr<T> find_regional_values_for_locale(StringView locale, GetRegional
return !container.is_empty();
};
if (auto regional_values = TRY(get_regional_values(locale)); has_value(regional_values))
if (auto regional_values = get_regional_values(locale); has_value(regional_values))
return regional_values;
auto return_default_values = [&]() { return get_regional_values("001"sv); };
@ -118,35 +118,29 @@ static ErrorOr<T> find_regional_values_for_locale(StringView locale, GetRegional
if (!language.has_value() || !language->region.has_value())
return return_default_values();
if (auto regional_values = TRY(get_regional_values(*language->region)); has_value(regional_values))
if (auto regional_values = get_regional_values(*language->region); has_value(regional_values))
return regional_values;
return return_default_values();
}
template<typename T, typename GetRegionalValues>
static ErrorOr<T> find_regional_values_for_locale(StringView locale, GetRegionalValues&& get_regional_values)
{
return find_regional_values_for_locale<T>(locale, [&](auto region) -> ErrorOr<T> { return get_regional_values(region); });
}
// https://unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table
ErrorOr<Vector<HourCycle>> get_locale_hour_cycles(StringView locale)
Vector<HourCycle> get_locale_hour_cycles(StringView locale)
{
return find_regional_values_for_locale<Vector<HourCycle>>(locale, get_regional_hour_cycles);
}
ErrorOr<Optional<HourCycle>> get_default_regional_hour_cycle(StringView locale)
Optional<HourCycle> get_default_regional_hour_cycle(StringView locale)
{
if (auto hour_cycles = TRY(get_locale_hour_cycles(locale)); !hour_cycles.is_empty())
if (auto hour_cycles = get_locale_hour_cycles(locale); !hour_cycles.is_empty())
return hour_cycles.first();
return OptionalNone {};
return {};
}
Optional<MinimumDaysRegion> __attribute__((weak)) minimum_days_region_from_string(StringView) { return {}; }
Optional<u8> __attribute__((weak)) get_regional_minimum_days(StringView) { return {}; }
ErrorOr<Optional<u8>> get_locale_minimum_days(StringView locale)
Optional<u8> get_locale_minimum_days(StringView locale)
{
return find_regional_values_for_locale<Optional<u8>>(locale, get_regional_minimum_days);
}
@ -154,7 +148,7 @@ ErrorOr<Optional<u8>> get_locale_minimum_days(StringView locale)
Optional<FirstDayRegion> __attribute__((weak)) first_day_region_from_string(StringView) { return {}; }
Optional<Weekday> __attribute__((weak)) get_regional_first_day(StringView) { return {}; }
ErrorOr<Optional<Weekday>> get_locale_first_day(StringView locale)
Optional<Weekday> get_locale_first_day(StringView locale)
{
return find_regional_values_for_locale<Optional<Weekday>>(locale, get_regional_first_day);
}
@ -162,7 +156,7 @@ ErrorOr<Optional<Weekday>> get_locale_first_day(StringView locale)
Optional<WeekendStartRegion> __attribute__((weak)) weekend_start_region_from_string(StringView) { return {}; }
Optional<Weekday> __attribute__((weak)) get_regional_weekend_start(StringView) { return {}; }
ErrorOr<Optional<Weekday>> get_locale_weekend_start(StringView locale)
Optional<Weekday> get_locale_weekend_start(StringView locale)
{
return find_regional_values_for_locale<Optional<Weekday>>(locale, get_regional_weekend_start);
}
@ -170,12 +164,12 @@ ErrorOr<Optional<Weekday>> get_locale_weekend_start(StringView locale)
Optional<WeekendEndRegion> __attribute__((weak)) weekend_end_region_from_string(StringView) { return {}; }
Optional<Weekday> __attribute__((weak)) get_regional_weekend_end(StringView) { return {}; }
ErrorOr<Optional<Weekday>> get_locale_weekend_end(StringView locale)
Optional<Weekday> get_locale_weekend_end(StringView locale)
{
return find_regional_values_for_locale<Optional<Weekday>>(locale, get_regional_weekend_end);
}
ErrorOr<String> combine_skeletons(StringView first, StringView second)
String combine_skeletons(StringView first, StringView second)
{
// https://unicode.org/reports/tr35/tr35-dates.html#availableFormats_appendItems
constexpr auto field_order = Array {
@ -193,34 +187,34 @@ ErrorOr<String> combine_skeletons(StringView first, StringView second)
StringBuilder builder;
auto append_from_skeleton = [&](auto skeleton, auto ch) -> ErrorOr<bool> {
auto append_from_skeleton = [&](auto skeleton, auto ch) {
auto first_index = skeleton.find(ch);
if (!first_index.has_value())
return false;
auto last_index = skeleton.find_last(ch);
TRY(builder.try_append(skeleton.substring_view(*first_index, *last_index - *first_index + 1)));
builder.append(skeleton.substring_view(*first_index, *last_index - *first_index + 1));
return true;
};
for (auto fields : field_order) {
for (auto ch : fields) {
if (TRY(append_from_skeleton(first, ch)))
if (append_from_skeleton(first, ch))
break;
if (TRY(append_from_skeleton(second, ch)))
if (append_from_skeleton(second, ch))
break;
}
}
return builder.to_string();
return MUST(builder.to_string());
}
ErrorOr<Optional<CalendarFormat>> __attribute__((weak)) get_calendar_date_format(StringView, StringView) { return OptionalNone {}; }
ErrorOr<Optional<CalendarFormat>> __attribute__((weak)) get_calendar_time_format(StringView, StringView) { return OptionalNone {}; }
ErrorOr<Optional<CalendarFormat>> __attribute__((weak)) get_calendar_date_time_format(StringView, StringView) { return OptionalNone {}; }
Optional<CalendarFormat> __attribute__((weak)) get_calendar_date_format(StringView, StringView) { return {}; }
Optional<CalendarFormat> __attribute__((weak)) get_calendar_time_format(StringView, StringView) { return {}; }
Optional<CalendarFormat> __attribute__((weak)) get_calendar_date_time_format(StringView, StringView) { return {}; }
ErrorOr<Optional<CalendarFormat>> get_calendar_format(StringView locale, StringView calendar, CalendarFormatType type)
Optional<CalendarFormat> get_calendar_format(StringView locale, StringView calendar, CalendarFormatType type)
{
switch (type) {
case CalendarFormatType::Date:
@ -234,31 +228,31 @@ ErrorOr<Optional<CalendarFormat>> get_calendar_format(StringView locale, StringV
}
}
ErrorOr<Vector<CalendarPattern>> __attribute__((weak)) get_calendar_available_formats(StringView, StringView) { return Vector<CalendarPattern> {}; }
ErrorOr<Optional<CalendarRangePattern>> __attribute__((weak)) get_calendar_default_range_format(StringView, StringView) { return OptionalNone {}; }
ErrorOr<Vector<CalendarRangePattern>> __attribute__((weak)) get_calendar_range_formats(StringView, StringView, StringView) { return Vector<CalendarRangePattern> {}; }
ErrorOr<Vector<CalendarRangePattern>> __attribute__((weak)) get_calendar_range12_formats(StringView, StringView, StringView) { return Vector<CalendarRangePattern> {}; }
ErrorOr<Optional<StringView>> __attribute__((weak)) get_calendar_era_symbol(StringView, StringView, CalendarPatternStyle, Era) { return OptionalNone {}; }
ErrorOr<Optional<StringView>> __attribute__((weak)) get_calendar_month_symbol(StringView, StringView, CalendarPatternStyle, Month) { return OptionalNone {}; }
ErrorOr<Optional<StringView>> __attribute__((weak)) get_calendar_weekday_symbol(StringView, StringView, CalendarPatternStyle, Weekday) { return OptionalNone {}; }
ErrorOr<Optional<StringView>> __attribute__((weak)) get_calendar_day_period_symbol(StringView, StringView, CalendarPatternStyle, DayPeriod) { return OptionalNone {}; }
ErrorOr<Optional<StringView>> __attribute__((weak)) get_calendar_day_period_symbol_for_hour(StringView, StringView, CalendarPatternStyle, u8) { return OptionalNone {}; }
Vector<CalendarPattern> __attribute__((weak)) get_calendar_available_formats(StringView, StringView) { return {}; }
Optional<CalendarRangePattern> __attribute__((weak)) get_calendar_default_range_format(StringView, StringView) { return {}; }
Vector<CalendarRangePattern> __attribute__((weak)) get_calendar_range_formats(StringView, StringView, StringView) { return {}; }
Vector<CalendarRangePattern> __attribute__((weak)) get_calendar_range12_formats(StringView, StringView, StringView) { return {}; }
Optional<StringView> __attribute__((weak)) get_calendar_era_symbol(StringView, StringView, CalendarPatternStyle, Era) { return {}; }
Optional<StringView> __attribute__((weak)) get_calendar_month_symbol(StringView, StringView, CalendarPatternStyle, Month) { return {}; }
Optional<StringView> __attribute__((weak)) get_calendar_weekday_symbol(StringView, StringView, CalendarPatternStyle, Weekday) { return {}; }
Optional<StringView> __attribute__((weak)) get_calendar_day_period_symbol(StringView, StringView, CalendarPatternStyle, DayPeriod) { return {}; }
Optional<StringView> __attribute__((weak)) get_calendar_day_period_symbol_for_hour(StringView, StringView, CalendarPatternStyle, u8) { return {}; }
Optional<StringView> __attribute__((weak)) get_time_zone_name(StringView, StringView, CalendarPatternStyle, TimeZone::InDST) { return {}; }
Optional<TimeZoneFormat> __attribute__((weak)) get_time_zone_format(StringView) { return {}; }
static ErrorOr<Optional<String>> format_time_zone_offset(StringView locale, CalendarPatternStyle style, i64 offset_seconds)
static Optional<String> format_time_zone_offset(StringView locale, CalendarPatternStyle style, i64 offset_seconds)
{
auto formats = get_time_zone_format(locale);
if (!formats.has_value())
return OptionalNone {};
return {};
auto number_system = get_preferred_keyword_value_for_locale(locale, "nu"sv);
if (!number_system.has_value())
return OptionalNone {};
return {};
if (offset_seconds == 0)
return String::from_utf8(formats->gmt_zero_format);
return MUST(String::from_utf8(formats->gmt_zero_format));
auto sign = offset_seconds > 0 ? formats->symbol_ahead_sign : formats->symbol_behind_sign;
auto separator = offset_seconds > 0 ? formats->symbol_ahead_separator : formats->symbol_behind_separator;
@ -271,23 +265,23 @@ static ErrorOr<Optional<String>> format_time_zone_offset(StringView locale, Cale
offset_seconds %= 60;
StringBuilder builder;
TRY(builder.try_append(sign));
builder.append(sign);
switch (style) {
// The long format always uses 2-digit hours field and minutes field, with optional 2-digit seconds field.
case CalendarPatternStyle::LongOffset:
TRY(builder.try_appendff("{:02}{}{:02}", offset_hours, separator, offset_minutes));
builder.appendff("{:02}{}{:02}", offset_hours, separator, offset_minutes);
if (offset_seconds > 0)
TRY(builder.try_appendff("{}{:02}", separator, offset_seconds));
builder.appendff("{}{:02}", separator, offset_seconds);
break;
// The short format is intended for the shortest representation and uses hour fields without leading zero, with optional 2-digit minutes and seconds fields.
case CalendarPatternStyle::ShortOffset:
TRY(builder.try_appendff("{}", offset_hours));
builder.appendff("{}", offset_hours);
if (offset_minutes > 0) {
TRY(builder.try_appendff("{}{:02}", separator, offset_minutes));
builder.appendff("{}{:02}", separator, offset_minutes);
if (offset_seconds > 0)
TRY(builder.try_appendff("{}{:02}", separator, offset_seconds));
builder.appendff("{}{:02}", separator, offset_seconds);
}
break;
@ -296,16 +290,16 @@ static ErrorOr<Optional<String>> format_time_zone_offset(StringView locale, Cale
}
// The digits used for hours, minutes and seconds fields in this format are the locale's default decimal digits.
auto result = replace_digits_for_number_system(*number_system, TRY(builder.to_string()));
return TRY(String::from_utf8(formats->gmt_format)).replace("{0}"sv, result, ReplaceMode::FirstOnly);
auto result = replace_digits_for_number_system(*number_system, builder.string_view());
return MUST(MUST(String::from_utf8(formats->gmt_format)).replace("{0}"sv, result, ReplaceMode::FirstOnly));
}
// https://unicode.org/reports/tr35/tr35-dates.html#Time_Zone_Format_Terminology
ErrorOr<String> format_time_zone(StringView locale, StringView time_zone, CalendarPatternStyle style, AK::UnixDateTime time)
String format_time_zone(StringView locale, StringView time_zone, CalendarPatternStyle style, AK::UnixDateTime time)
{
auto offset = TimeZone::get_time_zone_offset(time_zone, time);
if (!offset.has_value())
return String::from_utf8(time_zone);
return MUST(String::from_utf8(time_zone));
switch (style) {
case CalendarPatternStyle::Short:
@ -313,14 +307,14 @@ ErrorOr<String> format_time_zone(StringView locale, StringView time_zone, Calend
case CalendarPatternStyle::ShortGeneric:
case CalendarPatternStyle::LongGeneric:
if (auto name = get_time_zone_name(locale, time_zone, style, offset->in_dst); name.has_value())
return String::from_utf8(*name);
return MUST(String::from_utf8(*name));
break;
case CalendarPatternStyle::ShortOffset:
case CalendarPatternStyle::LongOffset:
if (auto formatted_offset = TRY(format_time_zone_offset(locale, style, offset->seconds)); formatted_offset.has_value())
if (auto formatted_offset = format_time_zone_offset(locale, style, offset->seconds); formatted_offset.has_value())
return formatted_offset.release_value();
return String::from_utf8(time_zone);
return MUST(String::from_utf8(time_zone));
default:
VERIFY_NOT_REACHED();

View File

@ -6,7 +6,6 @@
#pragma once
#include <AK/Error.h>
#include <AK/Optional.h>
#include <AK/String.h>
#include <AK/StringView.h>
@ -189,44 +188,44 @@ CalendarPatternStyle calendar_pattern_style_from_string(StringView style);
StringView calendar_pattern_style_to_string(CalendarPatternStyle style);
Optional<HourCycleRegion> hour_cycle_region_from_string(StringView hour_cycle_region);
ErrorOr<Vector<HourCycle>> get_regional_hour_cycles(StringView region);
ErrorOr<Vector<HourCycle>> get_locale_hour_cycles(StringView locale);
ErrorOr<Optional<HourCycle>> get_default_regional_hour_cycle(StringView locale);
Vector<HourCycle> get_regional_hour_cycles(StringView region);
Vector<HourCycle> get_locale_hour_cycles(StringView locale);
Optional<HourCycle> get_default_regional_hour_cycle(StringView locale);
Optional<MinimumDaysRegion> minimum_days_region_from_string(StringView minimum_days_region);
Optional<u8> get_regional_minimum_days(StringView region);
ErrorOr<Optional<u8>> get_locale_minimum_days(StringView locale);
Optional<u8> get_locale_minimum_days(StringView locale);
Optional<FirstDayRegion> first_day_region_from_string(StringView first_day_region);
Optional<Weekday> get_regional_first_day(StringView region);
ErrorOr<Optional<Weekday>> get_locale_first_day(StringView locale);
Optional<Weekday> get_locale_first_day(StringView locale);
Optional<WeekendStartRegion> weekend_start_region_from_string(StringView weekend_start_region);
Optional<Weekday> get_regional_weekend_start(StringView region);
ErrorOr<Optional<Weekday>> get_locale_weekend_start(StringView locale);
Optional<Weekday> get_locale_weekend_start(StringView locale);
Optional<WeekendEndRegion> weekend_end_region_from_string(StringView weekend_end_region);
Optional<Weekday> get_regional_weekend_end(StringView region);
ErrorOr<Optional<Weekday>> get_locale_weekend_end(StringView locale);
Optional<Weekday> get_locale_weekend_end(StringView locale);
ErrorOr<String> combine_skeletons(StringView first, StringView second);
String combine_skeletons(StringView first, StringView second);
ErrorOr<Optional<CalendarFormat>> get_calendar_date_format(StringView locale, StringView calendar);
ErrorOr<Optional<CalendarFormat>> get_calendar_time_format(StringView locale, StringView calendar);
ErrorOr<Optional<CalendarFormat>> get_calendar_date_time_format(StringView locale, StringView calendar);
ErrorOr<Optional<CalendarFormat>> get_calendar_format(StringView locale, StringView calendar, CalendarFormatType type);
ErrorOr<Vector<CalendarPattern>> get_calendar_available_formats(StringView locale, StringView calendar);
ErrorOr<Optional<CalendarRangePattern>> get_calendar_default_range_format(StringView locale, StringView calendar);
ErrorOr<Vector<CalendarRangePattern>> get_calendar_range_formats(StringView locale, StringView calendar, StringView skeleton);
ErrorOr<Vector<CalendarRangePattern>> get_calendar_range12_formats(StringView locale, StringView calendar, StringView skeleton);
Optional<CalendarFormat> get_calendar_date_format(StringView locale, StringView calendar);
Optional<CalendarFormat> get_calendar_time_format(StringView locale, StringView calendar);
Optional<CalendarFormat> get_calendar_date_time_format(StringView locale, StringView calendar);
Optional<CalendarFormat> get_calendar_format(StringView locale, StringView calendar, CalendarFormatType type);
Vector<CalendarPattern> get_calendar_available_formats(StringView locale, StringView calendar);
Optional<CalendarRangePattern> get_calendar_default_range_format(StringView locale, StringView calendar);
Vector<CalendarRangePattern> get_calendar_range_formats(StringView locale, StringView calendar, StringView skeleton);
Vector<CalendarRangePattern> get_calendar_range12_formats(StringView locale, StringView calendar, StringView skeleton);
ErrorOr<Optional<StringView>> get_calendar_era_symbol(StringView locale, StringView calendar, CalendarPatternStyle style, Era value);
ErrorOr<Optional<StringView>> get_calendar_month_symbol(StringView locale, StringView calendar, CalendarPatternStyle style, Month value);
ErrorOr<Optional<StringView>> get_calendar_weekday_symbol(StringView locale, StringView calendar, CalendarPatternStyle style, Weekday value);
ErrorOr<Optional<StringView>> get_calendar_day_period_symbol(StringView locale, StringView calendar, CalendarPatternStyle style, DayPeriod value);
ErrorOr<Optional<StringView>> get_calendar_day_period_symbol_for_hour(StringView locale, StringView calendar, CalendarPatternStyle style, u8 hour);
Optional<StringView> get_calendar_era_symbol(StringView locale, StringView calendar, CalendarPatternStyle style, Era value);
Optional<StringView> get_calendar_month_symbol(StringView locale, StringView calendar, CalendarPatternStyle style, Month value);
Optional<StringView> get_calendar_weekday_symbol(StringView locale, StringView calendar, CalendarPatternStyle style, Weekday value);
Optional<StringView> get_calendar_day_period_symbol(StringView locale, StringView calendar, CalendarPatternStyle style, DayPeriod value);
Optional<StringView> get_calendar_day_period_symbol_for_hour(StringView locale, StringView calendar, CalendarPatternStyle style, u8 hour);
ErrorOr<String> format_time_zone(StringView locale, StringView time_zone, CalendarPatternStyle style, AK::UnixDateTime time);
String format_time_zone(StringView locale, StringView time_zone, CalendarPatternStyle style, AK::UnixDateTime time);
Optional<StringView> get_time_zone_name(StringView locale, StringView time_zone, CalendarPatternStyle style, TimeZone::InDST in_dst);
Optional<TimeZoneFormat> get_time_zone_format(StringView locale);