mirror of
https://github.com/SerenityOS/serenity.git
synced 2025-01-23 01:41:59 -05:00
LibJS+LibLocale: Port Intl.DateTimeFormat to String
This commit is contained in:
parent
970e9df245
commit
b2097f4059
8 changed files with 223 additions and 197 deletions
|
@ -715,7 +715,7 @@ static constexpr auto is_char(char ch)
|
|||
// "{hour}:{minute} {ampm}" becomes "{hour}:{minute}" (remove the space before {ampm})
|
||||
// "{ampm} {hour}" becomes "{hour}" (remove the space after {ampm})
|
||||
// "{hour}:{minute} {ampm} {timeZoneName}" becomes "{hour}:{minute} {timeZoneName}" (remove one of the spaces around {ampm})
|
||||
static DeprecatedString remove_period_from_pattern(DeprecatedString pattern)
|
||||
static ErrorOr<String> remove_period_from_pattern(String pattern)
|
||||
{
|
||||
auto is_surrounding_space = [&](auto code_point_iterator) {
|
||||
if (code_point_iterator.done())
|
||||
|
@ -738,7 +738,7 @@ static DeprecatedString remove_period_from_pattern(DeprecatedString pattern)
|
|||
};
|
||||
|
||||
for (auto remove : AK::Array { "({ampm})"sv, "{ampm}"sv, "({dayPeriod})"sv, "{dayPeriod}"sv }) {
|
||||
auto index = pattern.find(remove);
|
||||
auto index = pattern.find_byte_offset(remove);
|
||||
if (!index.has_value())
|
||||
continue;
|
||||
|
||||
|
@ -751,25 +751,27 @@ static DeprecatedString remove_period_from_pattern(DeprecatedString pattern)
|
|||
if (auto it = utf8_pattern.iterator_at_byte_offset(*index + remove.length()); it != utf8_pattern.end())
|
||||
after_removal = it;
|
||||
|
||||
auto pattern_view = pattern.bytes_as_string_view();
|
||||
|
||||
if (is_surrounding_space(before_removal) && !is_opening(after_removal)) {
|
||||
pattern = DeprecatedString::formatted("{}{}",
|
||||
pattern.substring_view(0, *index - before_removal.underlying_code_point_length_in_bytes()),
|
||||
pattern.substring_view(*index + remove.length()));
|
||||
pattern = TRY(String::formatted("{}{}",
|
||||
pattern_view.substring_view(0, *index - before_removal.underlying_code_point_length_in_bytes()),
|
||||
pattern_view.substring_view(*index + remove.length())));
|
||||
} else if (is_surrounding_space(after_removal) && !is_closing(before_removal)) {
|
||||
pattern = DeprecatedString::formatted("{}{}",
|
||||
pattern.substring_view(0, *index),
|
||||
pattern.substring_view(*index + remove.length() + after_removal.underlying_code_point_length_in_bytes()));
|
||||
pattern = TRY(String::formatted("{}{}",
|
||||
pattern_view.substring_view(0, *index),
|
||||
pattern_view.substring_view(*index + remove.length() + after_removal.underlying_code_point_length_in_bytes())));
|
||||
} else {
|
||||
pattern = DeprecatedString::formatted("{}{}",
|
||||
pattern.substring_view(0, *index),
|
||||
pattern.substring_view(*index + remove.length()));
|
||||
pattern = TRY(String::formatted("{}{}",
|
||||
pattern_view.substring_view(0, *index),
|
||||
pattern_view.substring_view(*index + remove.length())));
|
||||
}
|
||||
}
|
||||
|
||||
return pattern;
|
||||
}
|
||||
|
||||
static Optional<CalendarPattern> parse_date_time_pattern_raw(DeprecatedString pattern, DeprecatedString skeleton, CLDR& cldr)
|
||||
static ErrorOr<Optional<CalendarPattern>> parse_date_time_pattern_raw(DeprecatedString pattern, DeprecatedString skeleton, CLDR& cldr)
|
||||
{
|
||||
// https://unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table
|
||||
using Locale::CalendarPatternStyle;
|
||||
|
@ -819,7 +821,7 @@ static Optional<CalendarPattern> parse_date_time_pattern_raw(DeprecatedString pa
|
|||
// Quarter
|
||||
else if (all_of(segment, is_any_of("qQ"sv))) {
|
||||
// Intl.DateTimeFormat does not support quarter formatting, so drop these patterns.
|
||||
return {};
|
||||
return OptionalNone {};
|
||||
}
|
||||
|
||||
// Month
|
||||
|
@ -838,13 +840,13 @@ static Optional<CalendarPattern> parse_date_time_pattern_raw(DeprecatedString pa
|
|||
format.month = CalendarPatternStyle::Narrow;
|
||||
} else if (all_of(segment, is_char('l'))) {
|
||||
// Using 'l' for month formatting is deprecated by TR-35, ensure it is not used.
|
||||
return {};
|
||||
return OptionalNone {};
|
||||
}
|
||||
|
||||
// Week
|
||||
else if (all_of(segment, is_any_of("wW"sv))) {
|
||||
// Intl.DateTimeFormat does not support week formatting, so drop these patterns.
|
||||
return {};
|
||||
return OptionalNone {};
|
||||
}
|
||||
|
||||
// Day
|
||||
|
@ -876,7 +878,7 @@ static Optional<CalendarPattern> parse_date_time_pattern_raw(DeprecatedString pa
|
|||
// TR-35 defines "e", "c", and "cc" as as numeric, and "ee" as 2-digit, but those
|
||||
// pattern styles are not supported by Intl.DateTimeFormat.
|
||||
if (segment.length() <= 2)
|
||||
return {};
|
||||
return OptionalNone {};
|
||||
|
||||
if (segment.length() == 4)
|
||||
format.weekday = CalendarPatternStyle::Long;
|
||||
|
@ -915,7 +917,7 @@ static Optional<CalendarPattern> parse_date_time_pattern_raw(DeprecatedString pa
|
|||
format.hour = CalendarPatternStyle::TwoDigit;
|
||||
} else if (all_of(segment, is_any_of("jJC"sv))) {
|
||||
// TR-35 indicates these should not be used.
|
||||
return {};
|
||||
return OptionalNone {};
|
||||
}
|
||||
|
||||
// Minute
|
||||
|
@ -943,7 +945,7 @@ static Optional<CalendarPattern> parse_date_time_pattern_raw(DeprecatedString pa
|
|||
format.fractional_second_digits = static_cast<u8>(segment.length());
|
||||
} else if (all_of(segment, is_char('A'))) {
|
||||
// Intl.DateTimeFormat does not support millisecond formatting, so drop these patterns.
|
||||
return {};
|
||||
return OptionalNone {};
|
||||
}
|
||||
|
||||
// Zone
|
||||
|
@ -976,30 +978,30 @@ static Optional<CalendarPattern> parse_date_time_pattern_raw(DeprecatedString pa
|
|||
}
|
||||
}
|
||||
|
||||
pattern = builder.build();
|
||||
auto parsed_pattern = TRY(builder.to_string());
|
||||
|
||||
if (hour12) {
|
||||
format.pattern = remove_period_from_pattern(pattern);
|
||||
format.pattern12 = move(pattern);
|
||||
format.pattern = TRY(remove_period_from_pattern(parsed_pattern));
|
||||
format.pattern12 = move(parsed_pattern);
|
||||
} else {
|
||||
format.pattern = move(pattern);
|
||||
format.pattern = move(parsed_pattern);
|
||||
}
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
static Optional<size_t> parse_date_time_pattern(DeprecatedString pattern, DeprecatedString skeleton, CLDR& cldr)
|
||||
static ErrorOr<Optional<size_t>> parse_date_time_pattern(DeprecatedString pattern, DeprecatedString skeleton, CLDR& cldr)
|
||||
{
|
||||
auto format = parse_date_time_pattern_raw(move(pattern), move(skeleton), cldr);
|
||||
auto format = TRY(parse_date_time_pattern_raw(move(pattern), move(skeleton), cldr));
|
||||
if (!format.has_value())
|
||||
return {};
|
||||
return OptionalNone {};
|
||||
|
||||
format->pattern_index = cldr.unique_strings.ensure(move(format->pattern));
|
||||
format->pattern_index = cldr.unique_strings.ensure(format->pattern.to_deprecated_string());
|
||||
|
||||
if (format->pattern12.has_value())
|
||||
format->pattern12_index = cldr.unique_strings.ensure(format->pattern12.release_value());
|
||||
format->pattern12_index = cldr.unique_strings.ensure(format->pattern12->to_deprecated_string());
|
||||
|
||||
return cldr.unique_patterns.ensure(format.release_value());
|
||||
return Optional<size_t> { cldr.unique_patterns.ensure(format.release_value()) };
|
||||
}
|
||||
|
||||
template<typename... Chars>
|
||||
|
@ -1008,7 +1010,7 @@ static constexpr bool char_is_one_of(char ch, Chars&&... chars)
|
|||
return ((ch == chars) || ...);
|
||||
}
|
||||
|
||||
static void parse_interval_patterns(Calendar& calendar, JsonObject const& interval_formats_object, CLDR& cldr)
|
||||
static ErrorOr<void> parse_interval_patterns(Calendar& calendar, JsonObject const& interval_formats_object, CLDR& cldr)
|
||||
{
|
||||
// https://unicode.org/reports/tr35/tr35-dates.html#intervalFormats
|
||||
CalendarRangePatternList range_formats {};
|
||||
|
@ -1060,28 +1062,29 @@ static void parse_interval_patterns(Calendar& calendar, JsonObject const& interv
|
|||
HashMap<StringView, size_t> partitions;
|
||||
StringView last_partition;
|
||||
|
||||
auto begin_index = pattern.find('{');
|
||||
auto begin_index = pattern.find_byte_offset('{');
|
||||
size_t end_index = 0;
|
||||
|
||||
while (begin_index.has_value()) {
|
||||
end_index = pattern.find('}', *begin_index).value();
|
||||
end_index = pattern.find_byte_offset('}', *begin_index).value();
|
||||
|
||||
auto partition = pattern.substring_view(*begin_index, end_index - *begin_index);
|
||||
auto partition = pattern.bytes_as_string_view().substring_view(*begin_index, end_index - *begin_index);
|
||||
if (partitions.contains(partition))
|
||||
break;
|
||||
|
||||
partitions.set(partition, *begin_index);
|
||||
last_partition = partition;
|
||||
|
||||
begin_index = pattern.find('{', end_index + 1);
|
||||
begin_index = pattern.find_byte_offset('{', end_index + 1);
|
||||
}
|
||||
|
||||
VERIFY(begin_index.has_value() && !last_partition.is_empty());
|
||||
auto start_range_end = partitions.get(last_partition).value() + last_partition.length() + 1;
|
||||
|
||||
auto start_range = pattern.substring_view(0, start_range_end);
|
||||
auto separator = pattern.substring_view(start_range_end, *begin_index - start_range_end);
|
||||
auto end_range = pattern.substring_view(*begin_index);
|
||||
auto pattern_view = pattern.bytes_as_string_view();
|
||||
auto start_range = pattern_view.substring_view(0, start_range_end);
|
||||
auto separator = pattern_view.substring_view(start_range_end, *begin_index - start_range_end);
|
||||
auto end_range = pattern_view.substring_view(*begin_index);
|
||||
|
||||
CalendarRangePattern format {};
|
||||
format.skeleton_index = cldr.unique_strings.ensure(skeleton);
|
||||
|
@ -1097,21 +1100,21 @@ static void parse_interval_patterns(Calendar& calendar, JsonObject const& interv
|
|||
return format;
|
||||
};
|
||||
|
||||
interval_formats_object.for_each_member([&](auto const& skeleton, auto const& value) {
|
||||
TRY(interval_formats_object.try_for_each_member([&](auto const& skeleton, auto const& value) -> ErrorOr<void> {
|
||||
if (skeleton == "intervalFormatFallback"sv) {
|
||||
auto range_format = split_default_range_pattern(skeleton, value.as_string());
|
||||
calendar.default_range_format = cldr.unique_range_patterns.ensure(move(range_format));
|
||||
return;
|
||||
return {};
|
||||
}
|
||||
|
||||
value.as_object().for_each_member([&](auto const& field, auto const& pattern) {
|
||||
TRY(value.as_object().try_for_each_member([&](auto const& field, auto const& pattern) -> ErrorOr<void> {
|
||||
if (field.ends_with("alt-variant"sv))
|
||||
return;
|
||||
return {};
|
||||
|
||||
VERIFY(field.length() == 1);
|
||||
auto name = name_of_field(field[0]);
|
||||
|
||||
auto format = parse_date_time_pattern_raw(pattern.as_string(), skeleton, cldr).release_value();
|
||||
auto format = TRY(parse_date_time_pattern_raw(pattern.as_string(), skeleton, cldr)).release_value();
|
||||
|
||||
auto range_format = split_range_pattern(skeleton, name, format.pattern, format);
|
||||
range_formats.append(cldr.unique_range_patterns.ensure(move(range_format)));
|
||||
|
@ -1122,26 +1125,34 @@ static void parse_interval_patterns(Calendar& calendar, JsonObject const& interv
|
|||
} else {
|
||||
range12_formats.append(range_formats.last());
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return {};
|
||||
}));
|
||||
|
||||
return {};
|
||||
}));
|
||||
|
||||
calendar.range_formats = cldr.unique_range_pattern_lists.ensure(move(range_formats));
|
||||
calendar.range12_formats = cldr.unique_range_pattern_lists.ensure(move(range12_formats));
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
static void generate_default_patterns(CalendarPatternList& formats, CLDR& cldr)
|
||||
static ErrorOr<void> generate_default_patterns(CalendarPatternList& formats, CLDR& cldr)
|
||||
{
|
||||
// For compatibility with ICU, we generate a list of default patterns for every locale:
|
||||
// https://github.com/unicode-org/icu/blob/release-71-1/icu4c/source/i18n/dtptngen.cpp#L1343-L1354=
|
||||
static constexpr auto default_patterns = Array { "G"sv, "y"sv, "M"sv, "E"sv, "D"sv, "F"sv, "d"sv, "a"sv, "B"sv, "H"sv, "mm"sv, "ss"sv, "SS"sv, "v"sv };
|
||||
|
||||
for (auto pattern : default_patterns) {
|
||||
auto index = parse_date_time_pattern(pattern, pattern, cldr);
|
||||
auto index = TRY(parse_date_time_pattern(pattern, pattern, cldr));
|
||||
VERIFY(index.has_value());
|
||||
|
||||
if (!formats.contains_slow(*index))
|
||||
formats.append(*index);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
static void generate_missing_patterns(Calendar& calendar, CalendarPatternList& formats, Vector<CalendarPattern> date_formats, Vector<CalendarPattern> time_formats, CLDR& cldr)
|
||||
|
@ -1390,12 +1401,12 @@ static ErrorOr<void> parse_calendars(DeprecatedString locale_calendars_path, CLD
|
|||
auto const& dates_object = locale_object.get_object("dates"sv).value();
|
||||
auto const& calendars_object = dates_object.get_object("calendars"sv).value();
|
||||
|
||||
auto parse_patterns = [&](auto const& patterns_object, auto const& skeletons_object, Vector<CalendarPattern>* patterns) {
|
||||
auto parse_pattern = [&](auto name) {
|
||||
auto parse_patterns = [&](auto const& patterns_object, auto const& skeletons_object, Vector<CalendarPattern>* patterns) -> ErrorOr<size_t> {
|
||||
auto parse_pattern = [&](auto name) -> ErrorOr<size_t> {
|
||||
auto format = patterns_object.get_deprecated_string(name);
|
||||
auto skeleton = skeletons_object.get_deprecated_string(name);
|
||||
|
||||
auto format_index = parse_date_time_pattern(format.value(), skeleton.value_or(DeprecatedString::empty()), cldr).value();
|
||||
auto format_index = TRY(parse_date_time_pattern(format.value(), skeleton.value_or(DeprecatedString::empty()), cldr)).value();
|
||||
|
||||
if (patterns)
|
||||
patterns->append(cldr.unique_patterns.get(format_index));
|
||||
|
@ -1404,19 +1415,19 @@ static ErrorOr<void> parse_calendars(DeprecatedString locale_calendars_path, CLD
|
|||
};
|
||||
|
||||
CalendarFormat formats {};
|
||||
formats.full_format = parse_pattern("full"sv);
|
||||
formats.long_format = parse_pattern("long"sv);
|
||||
formats.medium_format = parse_pattern("medium"sv);
|
||||
formats.short_format = parse_pattern("short"sv);
|
||||
formats.full_format = TRY(parse_pattern("full"sv));
|
||||
formats.long_format = TRY(parse_pattern("long"sv));
|
||||
formats.medium_format = TRY(parse_pattern("medium"sv));
|
||||
formats.short_format = TRY(parse_pattern("short"sv));
|
||||
|
||||
return cldr.unique_formats.ensure(move(formats));
|
||||
};
|
||||
|
||||
calendars_object.for_each_member([&](auto const& calendar_name, JsonValue const& value) {
|
||||
TRY(calendars_object.try_for_each_member([&](auto const& calendar_name, JsonValue const& value) -> ErrorOr<void> {
|
||||
// The generic calendar is not a supported Unicode calendar key, so skip it:
|
||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/calendar#unicode_calendar_keys
|
||||
if (calendar_name == "generic"sv)
|
||||
return;
|
||||
return {};
|
||||
|
||||
Calendar calendar {};
|
||||
CalendarPatternList available_formats {};
|
||||
|
@ -1429,21 +1440,21 @@ static ErrorOr<void> parse_calendars(DeprecatedString locale_calendars_path, CLD
|
|||
|
||||
auto const& date_formats_object = value.as_object().get_object("dateFormats"sv).value();
|
||||
auto const& date_skeletons_object = value.as_object().get_object("dateSkeletons"sv).value();
|
||||
calendar.date_formats = parse_patterns(date_formats_object, date_skeletons_object, &date_formats);
|
||||
calendar.date_formats = TRY(parse_patterns(date_formats_object, date_skeletons_object, &date_formats));
|
||||
|
||||
auto const& time_formats_object = value.as_object().get_object("timeFormats"sv).value();
|
||||
auto const& time_skeletons_object = value.as_object().get_object("timeSkeletons"sv).value();
|
||||
calendar.time_formats = parse_patterns(time_formats_object, time_skeletons_object, &time_formats);
|
||||
calendar.time_formats = TRY(parse_patterns(time_formats_object, time_skeletons_object, &time_formats));
|
||||
|
||||
auto const& standard_date_time_formats_object = value.as_object().get_object("dateTimeFormats-atTime"sv)->get_object("standard"sv).value();
|
||||
calendar.date_time_formats = parse_patterns(standard_date_time_formats_object, JsonObject {}, nullptr);
|
||||
calendar.date_time_formats = TRY(parse_patterns(standard_date_time_formats_object, JsonObject {}, nullptr));
|
||||
|
||||
auto const& date_time_formats_object = value.as_object().get_object("dateTimeFormats"sv).value();
|
||||
auto const& available_formats_object = date_time_formats_object.get_object("availableFormats"sv).value();
|
||||
available_formats_object.for_each_member([&](auto const& skeleton, JsonValue const& pattern) {
|
||||
auto pattern_index = parse_date_time_pattern(pattern.as_string(), skeleton, cldr);
|
||||
TRY(available_formats_object.try_for_each_member([&](auto const& skeleton, JsonValue const& pattern) -> ErrorOr<void> {
|
||||
auto pattern_index = TRY(parse_date_time_pattern(pattern.as_string(), skeleton, cldr));
|
||||
if (!pattern_index.has_value())
|
||||
return;
|
||||
return {};
|
||||
|
||||
auto const& format = cldr.unique_patterns.get(*pattern_index);
|
||||
if (format.contains_only_date_fields())
|
||||
|
@ -1453,18 +1464,22 @@ static ErrorOr<void> parse_calendars(DeprecatedString locale_calendars_path, CLD
|
|||
|
||||
if (!available_formats.contains_slow(*pattern_index))
|
||||
available_formats.append(*pattern_index);
|
||||
});
|
||||
|
||||
return {};
|
||||
}));
|
||||
|
||||
auto const& interval_formats_object = date_time_formats_object.get_object("intervalFormats"sv).value();
|
||||
parse_interval_patterns(calendar, interval_formats_object, cldr);
|
||||
TRY(parse_interval_patterns(calendar, interval_formats_object, cldr));
|
||||
|
||||
generate_default_patterns(available_formats, cldr);
|
||||
TRY(generate_default_patterns(available_formats, cldr));
|
||||
generate_missing_patterns(calendar, available_formats, move(date_formats), move(time_formats), cldr);
|
||||
parse_calendar_symbols(calendar, value.as_object(), cldr);
|
||||
|
||||
calendar.available_formats = cldr.unique_pattern_lists.ensure(move(available_formats));
|
||||
locale.calendars.set(calendar_name, cldr.unique_calendars.ensure(move(calendar)));
|
||||
});
|
||||
|
||||
return {};
|
||||
}));
|
||||
|
||||
return {};
|
||||
}
|
||||
|
@ -1736,7 +1751,9 @@ static ErrorOr<void> generate_unicode_locale_implementation(Core::Stream::Buffer
|
|||
generator.append(R"~~~(
|
||||
#include <AK/Array.h>
|
||||
#include <AK/BinarySearch.h>
|
||||
#include <AK/Error.h>
|
||||
#include <AK/Optional.h>
|
||||
#include <AK/String.h>
|
||||
#include <AK/StringView.h>
|
||||
#include <LibLocale/DateTimeFormat.h>
|
||||
#include <LibLocale/DateTimeFormatData.h>
|
||||
|
@ -1778,13 +1795,13 @@ static void convert_calendar_fields(SourceType const& source, TargetType& target
|
|||
}
|
||||
|
||||
struct CalendarPatternImpl {
|
||||
CalendarPattern to_unicode_calendar_pattern() const {
|
||||
ErrorOr<CalendarPattern> to_unicode_calendar_pattern() const {
|
||||
CalendarPattern calendar_pattern {};
|
||||
|
||||
calendar_pattern.skeleton = decode_string(skeleton);
|
||||
calendar_pattern.pattern = decode_string(pattern);
|
||||
calendar_pattern.skeleton = TRY(String::from_utf8(decode_string(skeleton)));
|
||||
calendar_pattern.pattern = TRY(String::from_utf8(decode_string(pattern)));
|
||||
if (pattern12 != 0)
|
||||
calendar_pattern.pattern12 = decode_string(pattern12);
|
||||
calendar_pattern.pattern12 = TRY(String::from_utf8(decode_string(pattern12)));
|
||||
|
||||
convert_calendar_fields(*this, calendar_pattern);
|
||||
return calendar_pattern;
|
||||
|
@ -1808,14 +1825,14 @@ struct CalendarPatternImpl {
|
|||
};
|
||||
|
||||
struct CalendarRangePatternImpl {
|
||||
CalendarRangePattern to_unicode_calendar_range_pattern() const {
|
||||
ErrorOr<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 = decode_string(start_range);
|
||||
calendar_range_pattern.start_range = TRY(String::from_utf8(decode_string(start_range)));
|
||||
calendar_range_pattern.separator = decode_string(separator);
|
||||
calendar_range_pattern.end_range = decode_string(end_range);
|
||||
calendar_range_pattern.end_range = TRY(String::from_utf8(decode_string(end_range)));
|
||||
|
||||
convert_calendar_fields(*this, calendar_range_pattern);
|
||||
return calendar_range_pattern;
|
||||
|
@ -1848,13 +1865,13 @@ struct CalendarRangePatternImpl {
|
|||
|
||||
generator.append(R"~~~(
|
||||
struct CalendarFormatImpl {
|
||||
CalendarFormat to_unicode_calendar_format() const {
|
||||
ErrorOr<CalendarFormat> to_unicode_calendar_format() const {
|
||||
CalendarFormat calendar_format {};
|
||||
|
||||
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();
|
||||
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());
|
||||
|
||||
return calendar_format;
|
||||
}
|
||||
|
@ -2110,59 +2127,59 @@ static CalendarData const* find_calendar_data(StringView locale, StringView cale
|
|||
return lookup_calendar(*default_calendar);
|
||||
}
|
||||
|
||||
Optional<CalendarFormat> get_calendar_date_format(StringView locale, StringView calendar)
|
||||
ErrorOr<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 formats.to_unicode_calendar_format();
|
||||
return TRY(formats.to_unicode_calendar_format());
|
||||
}
|
||||
return {};
|
||||
return OptionalNone {};
|
||||
}
|
||||
|
||||
Optional<CalendarFormat> get_calendar_time_format(StringView locale, StringView calendar)
|
||||
ErrorOr<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 formats.to_unicode_calendar_format();
|
||||
return TRY(formats.to_unicode_calendar_format());
|
||||
}
|
||||
return {};
|
||||
return OptionalNone {};
|
||||
}
|
||||
|
||||
Optional<CalendarFormat> get_calendar_date_time_format(StringView locale, StringView calendar)
|
||||
ErrorOr<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 formats.to_unicode_calendar_format();
|
||||
return TRY(formats.to_unicode_calendar_format());
|
||||
}
|
||||
return {};
|
||||
return OptionalNone {};
|
||||
}
|
||||
|
||||
Vector<CalendarPattern> get_calendar_available_formats(StringView locale, StringView calendar)
|
||||
ErrorOr<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);
|
||||
result.ensure_capacity(available_formats.size());
|
||||
TRY(result.try_ensure_capacity(available_formats.size()));
|
||||
|
||||
for (auto const& format : available_formats)
|
||||
result.unchecked_append(s_calendar_patterns[format].to_unicode_calendar_pattern());
|
||||
result.unchecked_append(TRY(s_calendar_patterns[format].to_unicode_calendar_pattern()));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Optional<CalendarRangePattern> get_calendar_default_range_format(StringView locale, StringView calendar)
|
||||
ErrorOr<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 pattern.to_unicode_calendar_range_pattern();
|
||||
return TRY(pattern.to_unicode_calendar_range_pattern());
|
||||
}
|
||||
|
||||
return {};
|
||||
return OptionalNone {};
|
||||
}
|
||||
|
||||
Vector<CalendarRangePattern> get_calendar_range_formats(StringView locale, StringView calendar, StringView skeleton)
|
||||
ErrorOr<Vector<CalendarRangePattern>> get_calendar_range_formats(StringView locale, StringView calendar, StringView skeleton)
|
||||
{
|
||||
Vector<CalendarRangePattern> result {};
|
||||
|
||||
|
@ -2173,14 +2190,14 @@ Vector<CalendarRangePattern> get_calendar_range_formats(StringView locale, Strin
|
|||
auto const& pattern = s_calendar_range_patterns[format];
|
||||
|
||||
if (skeleton == decode_string(pattern.skeleton))
|
||||
result.append(pattern.to_unicode_calendar_range_pattern());
|
||||
TRY(result.try_append(TRY(pattern.to_unicode_calendar_range_pattern())));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Vector<CalendarRangePattern> get_calendar_range12_formats(StringView locale, StringView calendar, StringView skeleton)
|
||||
ErrorOr<Vector<CalendarRangePattern>> get_calendar_range12_formats(StringView locale, StringView calendar, StringView skeleton)
|
||||
{
|
||||
Vector<CalendarRangePattern> result {};
|
||||
|
||||
|
@ -2191,7 +2208,7 @@ Vector<CalendarRangePattern> get_calendar_range12_formats(StringView locale, Str
|
|||
auto const& pattern = s_calendar_range_patterns[format];
|
||||
|
||||
if (skeleton == decode_string(pattern.skeleton))
|
||||
result.append(pattern.to_unicode_calendar_range_pattern());
|
||||
TRY(result.try_append(TRY(pattern.to_unicode_calendar_range_pattern())));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ TEST_CASE(time_zone_name)
|
|||
constexpr auto jan_1_2022 = AK::Time::from_seconds(1640995200); // Saturday, January 1, 2022 12:00:00 AM
|
||||
|
||||
for (auto const& test : test_data) {
|
||||
auto time_zone = Locale::format_time_zone(test.locale, test.time_zone, test.style, jan_1_2022);
|
||||
auto time_zone = MUST(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::Time::from_seconds(1663553728); // Monday, September 19, 2022 2:15:28 AM
|
||||
|
||||
for (auto const& test : test_data) {
|
||||
auto time_zone = Locale::format_time_zone(test.locale, test.time_zone, test.style, sep_19_2022);
|
||||
auto time_zone = MUST(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 = Locale::format_time_zone(test.locale, test.time_zone, test.style, test.time);
|
||||
auto time_zone = MUST(Locale::format_time_zone(test.locale, test.time_zone, test.style, test.time));
|
||||
EXPECT_EQ(time_zone, test.expected_result);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -135,8 +135,8 @@ void TimeZoneSettingsWidget::set_time_zone_location()
|
|||
auto locale = Locale::default_locale();
|
||||
auto now = AK::Time::now_realtime();
|
||||
|
||||
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);
|
||||
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();
|
||||
|
||||
m_time_zone_text = DeprecatedString::formatted("{}\n({})", name, offset);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2021-2022, Tim Flynn <trflynn89@serenityos.org>
|
||||
* Copyright (c) 2021-2023, Tim Flynn <trflynn89@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -15,6 +15,7 @@
|
|||
#include <LibJS/Runtime/Intl/NumberFormat.h>
|
||||
#include <LibJS/Runtime/Intl/NumberFormatConstructor.h>
|
||||
#include <LibJS/Runtime/NativeFunction.h>
|
||||
#include <LibJS/Runtime/ThrowableStringBuilder.h>
|
||||
#include <LibJS/Runtime/Utf16String.h>
|
||||
#include <LibLocale/Locale.h>
|
||||
#include <LibLocale/NumberFormat.h>
|
||||
|
@ -153,13 +154,13 @@ ThrowCompletionOr<Object*> to_date_time_options(VM& vm, Value options_value, Opt
|
|||
}
|
||||
|
||||
// 11.5.2 DateTimeStyleFormat ( dateStyle, timeStyle, styles ), https://tc39.es/ecma402/#sec-date-time-style-format
|
||||
Optional<::Locale::CalendarPattern> date_time_style_format(StringView data_locale, DateTimeFormat& date_time_format)
|
||||
ThrowCompletionOr<Optional<::Locale::CalendarPattern>> date_time_style_format(VM& vm, StringView data_locale, DateTimeFormat& date_time_format)
|
||||
{
|
||||
::Locale::CalendarPattern time_format {};
|
||||
::Locale::CalendarPattern date_format {};
|
||||
|
||||
auto get_pattern = [&](auto type, auto style) -> Optional<::Locale::CalendarPattern> {
|
||||
auto formats = ::Locale::get_calendar_format(data_locale, date_time_format.calendar(), type);
|
||||
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));
|
||||
|
||||
if (formats.has_value()) {
|
||||
switch (style) {
|
||||
|
@ -174,16 +175,16 @@ Optional<::Locale::CalendarPattern> date_time_style_format(StringView data_local
|
|||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
return OptionalNone {};
|
||||
};
|
||||
|
||||
// 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 = get_pattern(::Locale::CalendarFormatType::Time, date_time_format.time_style());
|
||||
auto pattern = MUST_OR_THROW_OOM(get_pattern(::Locale::CalendarFormatType::Time, date_time_format.time_style()));
|
||||
if (!pattern.has_value())
|
||||
return {};
|
||||
return OptionalNone {};
|
||||
|
||||
time_format = pattern.release_value();
|
||||
}
|
||||
|
@ -192,9 +193,9 @@ Optional<::Locale::CalendarPattern> date_time_style_format(StringView data_local
|
|||
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 = get_pattern(::Locale::CalendarFormatType::Date, date_time_format.date_style());
|
||||
auto pattern = MUST_OR_THROW_OOM(get_pattern(::Locale::CalendarFormatType::Date, date_time_format.date_style()));
|
||||
if (!pattern.has_value())
|
||||
return {};
|
||||
return OptionalNone {};
|
||||
|
||||
date_format = pattern.release_value();
|
||||
}
|
||||
|
@ -216,12 +217,13 @@ Optional<::Locale::CalendarPattern> date_time_style_format(StringView data_local
|
|||
});
|
||||
|
||||
// d. Let connector be styles.[[DateTimeFormat]].[[<dateStyle>]].
|
||||
auto connector = get_pattern(::Locale::CalendarFormatType::DateTime, date_time_format.date_style());
|
||||
auto connector = MUST_OR_THROW_OOM(get_pattern(::Locale::CalendarFormatType::DateTime, date_time_format.date_style()));
|
||||
if (!connector.has_value())
|
||||
return {};
|
||||
return OptionalNone {};
|
||||
|
||||
// e. Let pattern be the string connector with the substring "{0}" replaced with timeFormat.[[pattern]] and the substring "{1}" replaced with dateFormat.[[pattern]].
|
||||
auto pattern = connector->pattern.replace("{0}"sv, time_format.pattern, ReplaceMode::FirstOnly).replace("{1}"sv, date_format.pattern, ReplaceMode::FirstOnly);
|
||||
auto pattern = TRY_OR_THROW_OOM(vm, connector->pattern.replace("{0}"sv, time_format.pattern, ReplaceMode::FirstOnly));
|
||||
pattern = TRY_OR_THROW_OOM(vm, pattern.replace("{1}"sv, date_format.pattern, ReplaceMode::FirstOnly));
|
||||
|
||||
// f. Set format.[[pattern]] to pattern.
|
||||
format.pattern = move(pattern);
|
||||
|
@ -229,7 +231,8 @@ Optional<::Locale::CalendarPattern> date_time_style_format(StringView data_local
|
|||
// g. If timeFormat has a [[pattern12]] field, then
|
||||
if (time_format.pattern12.has_value()) {
|
||||
// i. Let pattern12 be the string connector with the substring "{0}" replaced with timeFormat.[[pattern12]] and the substring "{1}" replaced with dateFormat.[[pattern]].
|
||||
auto pattern12 = connector->pattern.replace("{0}"sv, *time_format.pattern12, ReplaceMode::FirstOnly).replace("{1}"sv, date_format.pattern, ReplaceMode::FirstOnly);
|
||||
auto pattern12 = TRY_OR_THROW_OOM(vm, connector->pattern.replace("{0}"sv, *time_format.pattern12, ReplaceMode::FirstOnly));
|
||||
pattern12 = TRY_OR_THROW_OOM(vm, pattern12.replace("{1}"sv, date_format.pattern, ReplaceMode::FirstOnly));
|
||||
|
||||
// ii. Set format.[[pattern12]] to pattern12.
|
||||
format.pattern12 = move(pattern12);
|
||||
|
@ -238,7 +241,7 @@ Optional<::Locale::CalendarPattern> date_time_style_format(StringView data_local
|
|||
// 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 = ::Locale::combine_skeletons(date_format.skeleton, time_format.skeleton);
|
||||
format.skeleton = TRY_OR_THROW_OOM(vm, ::Locale::combine_skeletons(date_format.skeleton, time_format.skeleton));
|
||||
|
||||
// k. Return format.
|
||||
return format;
|
||||
|
@ -629,7 +632,7 @@ ThrowCompletionOr<Vector<PatternPartition>> format_date_time_pattern(VM& vm, Dat
|
|||
|
||||
// d. Else if p is equal to "dayPeriod", then
|
||||
else if (part == "dayPeriod"sv) {
|
||||
DeprecatedString formatted_value;
|
||||
String formatted_value;
|
||||
|
||||
// i. Let f be the value of dateTimeFormat's internal slot whose name is the Internal Slot column of the matching row.
|
||||
auto style = date_time_format.day_period();
|
||||
|
@ -637,10 +640,10 @@ ThrowCompletionOr<Vector<PatternPartition>> format_date_time_pattern(VM& vm, Dat
|
|||
// 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 = resolve_day_period(data_locale, date_time_format.calendar(), style, pattern_parts, local_time);
|
||||
if (symbol.has_value())
|
||||
formatted_value = *symbol;
|
||||
formatted_value = TRY_OR_THROW_OOM(vm, String::from_utf8(*symbol));
|
||||
|
||||
// iii. Append a new Record { [[Type]]: p, [[Value]]: fv } as the last element of the list result.
|
||||
result.append({ "dayPeriod"sv, TRY_OR_THROW_OOM(vm, String::from_deprecated_string(formatted_value)) });
|
||||
result.append({ "dayPeriod"sv, move(formatted_value) });
|
||||
}
|
||||
|
||||
// e. Else if p is equal to "timeZoneName", then
|
||||
|
@ -654,15 +657,15 @@ 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 = ::Locale::format_time_zone(data_locale, value, style, local_time.time_since_epoch());
|
||||
auto formatted_value = TRY_OR_THROW_OOM(vm, ::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.
|
||||
result.append({ "timeZoneName"sv, TRY_OR_THROW_OOM(vm, String::from_deprecated_string(formatted_value)) });
|
||||
result.append({ "timeZoneName"sv, move(formatted_value) });
|
||||
}
|
||||
|
||||
// f. Else if p matches a Property column of the row in Table 6, then
|
||||
else if (auto style_and_value = find_calendar_field(part, date_time_format, range_format_options, local_time); style_and_value.has_value()) {
|
||||
DeprecatedString formatted_value;
|
||||
String formatted_value;
|
||||
|
||||
// i. If rangeFormatOptions is not undefined, let f be the value of rangeFormatOptions's field whose name matches p.
|
||||
// ii. Else, let f be the value of dateTimeFormat's internal slot whose name is the Internal Slot column of the matching row.
|
||||
|
@ -705,20 +708,20 @@ ThrowCompletionOr<Vector<PatternPartition>> format_date_time_pattern(VM& vm, Dat
|
|||
// viii. If f is "numeric", then
|
||||
case ::Locale::CalendarPatternStyle::Numeric:
|
||||
// 1. Let fv be FormatNumeric(nf, v).
|
||||
formatted_value = MUST_OR_THROW_OOM(format_numeric(vm, *number_format, Value(value))).to_deprecated_string();
|
||||
formatted_value = MUST_OR_THROW_OOM(format_numeric(vm, *number_format, Value(value)));
|
||||
break;
|
||||
|
||||
// ix. Else if f is "2-digit", then
|
||||
case ::Locale::CalendarPatternStyle::TwoDigit:
|
||||
// 1. Let fv be FormatNumeric(nf2, v).
|
||||
formatted_value = MUST_OR_THROW_OOM(format_numeric(vm, *number_format2, Value(value))).to_deprecated_string();
|
||||
formatted_value = MUST_OR_THROW_OOM(format_numeric(vm, *number_format2, Value(value)));
|
||||
|
||||
// 2. If the "length" property of fv is greater than 2, let fv be the substring of fv containing the last two characters.
|
||||
// NOTE: The first length check here isn't enough, but lets us avoid UTF-16 transcoding when the formatted value is ASCII.
|
||||
if (formatted_value.length() > 2) {
|
||||
if (formatted_value.bytes_as_string_view().length() > 2) {
|
||||
auto utf16_formatted_value = TRY(Utf16String::create(vm, formatted_value));
|
||||
if (utf16_formatted_value.length_in_code_units() > 2)
|
||||
formatted_value = TRY_OR_THROW_OOM(vm, utf16_formatted_value.substring_view(utf16_formatted_value.length_in_code_units() - 2).to_deprecated_string());
|
||||
formatted_value = TRY_OR_THROW_OOM(vm, utf16_formatted_value.substring_view(utf16_formatted_value.length_in_code_units() - 2).to_utf8());
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -741,7 +744,11 @@ ThrowCompletionOr<Vector<PatternPartition>> format_date_time_pattern(VM& vm, Dat
|
|||
else if (part == "weekday"sv)
|
||||
symbol = ::Locale::get_calendar_weekday_symbol(data_locale, date_time_format.calendar(), style, static_cast<::Locale::Weekday>(value));
|
||||
|
||||
formatted_value = symbol.value_or(DeprecatedString::number(value));
|
||||
if (symbol.has_value())
|
||||
formatted_value = TRY_OR_THROW_OOM(vm, String::from_utf8(*symbol));
|
||||
else
|
||||
formatted_value = TRY_OR_THROW_OOM(vm, String::number(value));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -750,12 +757,12 @@ ThrowCompletionOr<Vector<PatternPartition>> format_date_time_pattern(VM& vm, Dat
|
|||
}
|
||||
|
||||
// xi. Append a new Record { [[Type]]: p, [[Value]]: fv } as the last element of the list result.
|
||||
result.append({ style_and_value->name, TRY_OR_THROW_OOM(vm, String::from_deprecated_string(formatted_value)) });
|
||||
result.append({ style_and_value->name, move(formatted_value) });
|
||||
}
|
||||
|
||||
// g. Else if p is equal to "ampm", then
|
||||
else if (part == "ampm"sv) {
|
||||
DeprecatedString formatted_value;
|
||||
String formatted_value;
|
||||
|
||||
// i. Let v be tm.[[Hour]].
|
||||
auto value = local_time.hour;
|
||||
|
@ -764,17 +771,17 @@ ThrowCompletionOr<Vector<PatternPartition>> format_date_time_pattern(VM& vm, Dat
|
|||
if (value > 11) {
|
||||
// 1. Let fv be an implementation and locale dependent String value representing "post meridiem".
|
||||
auto symbol = ::Locale::get_calendar_day_period_symbol(data_locale, date_time_format.calendar(), ::Locale::CalendarPatternStyle::Short, ::Locale::DayPeriod::PM);
|
||||
formatted_value = symbol.value_or("PM"sv);
|
||||
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 = ::Locale::get_calendar_day_period_symbol(data_locale, date_time_format.calendar(), ::Locale::CalendarPatternStyle::Short, ::Locale::DayPeriod::AM);
|
||||
formatted_value = symbol.value_or("AM"sv);
|
||||
formatted_value = TRY_OR_THROW_OOM(vm, String::from_utf8(symbol.value_or("AM"sv)));
|
||||
}
|
||||
|
||||
// iv. Append a new Record { [[Type]]: "dayPeriod", [[Value]]: fv } as the last element of the list result.
|
||||
result.append({ "dayPeriod"sv, TRY_OR_THROW_OOM(vm, String::from_deprecated_string(formatted_value)) });
|
||||
result.append({ "dayPeriod"sv, move(formatted_value) });
|
||||
}
|
||||
|
||||
// h. Else if p is equal to "relatedYear", then
|
||||
|
@ -830,22 +837,22 @@ ThrowCompletionOr<Vector<PatternPartition>> partition_date_time_pattern(VM& vm,
|
|||
}
|
||||
|
||||
// 11.5.8 FormatDateTime ( dateTimeFormat, x ), https://tc39.es/ecma402/#sec-formatdatetime
|
||||
ThrowCompletionOr<DeprecatedString> format_date_time(VM& vm, DateTimeFormat& date_time_format, double time)
|
||||
ThrowCompletionOr<String> format_date_time(VM& vm, DateTimeFormat& date_time_format, double time)
|
||||
{
|
||||
// 1. Let parts be ? PartitionDateTimePattern(dateTimeFormat, x).
|
||||
auto parts = TRY(partition_date_time_pattern(vm, date_time_format, time));
|
||||
|
||||
// 2. Let result be the empty String.
|
||||
StringBuilder result;
|
||||
ThrowableStringBuilder result(vm);
|
||||
|
||||
// 3. For each Record { [[Type]], [[Value]] } part in parts, do
|
||||
for (auto& part : parts) {
|
||||
// a. Set result to the string-concatenation of result and part.[[Value]].
|
||||
result.append(move(part.value));
|
||||
TRY(result.append(part.value));
|
||||
}
|
||||
|
||||
// 4. Return result.
|
||||
return result.build();
|
||||
return result.to_string();
|
||||
}
|
||||
|
||||
// 11.5.9 FormatDateTimeToParts ( dateTimeFormat, x ), https://tc39.es/ecma402/#sec-formatdatetimetoparts
|
||||
|
@ -1089,7 +1096,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 = ::Locale::get_calendar_default_range_format(date_time_format.data_locale(), date_time_format.calendar());
|
||||
range_pattern = TRY_OR_THROW_OOM(vm, ::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())
|
||||
|
@ -1100,11 +1107,11 @@ ThrowCompletionOr<Vector<PatternPartitionWithSource>> partition_date_time_range_
|
|||
auto const& pattern = date_time_format.pattern();
|
||||
|
||||
if (range_pattern->start_range.contains("{0}"sv)) {
|
||||
range_pattern->start_range = range_pattern->start_range.replace("{0}"sv, pattern, ReplaceMode::FirstOnly);
|
||||
range_pattern->end_range = range_pattern->end_range.replace("{1}"sv, pattern, ReplaceMode::FirstOnly);
|
||||
range_pattern->start_range = TRY_OR_THROW_OOM(vm, range_pattern->start_range.replace("{0}"sv, pattern, ReplaceMode::FirstOnly));
|
||||
range_pattern->end_range = TRY_OR_THROW_OOM(vm, range_pattern->end_range.replace("{1}"sv, pattern, ReplaceMode::FirstOnly));
|
||||
} else {
|
||||
range_pattern->start_range = range_pattern->start_range.replace("{1}"sv, pattern, ReplaceMode::FirstOnly);
|
||||
range_pattern->end_range = range_pattern->end_range.replace("{0}"sv, pattern, ReplaceMode::FirstOnly);
|
||||
range_pattern->start_range = TRY_OR_THROW_OOM(vm, range_pattern->start_range.replace("{1}"sv, pattern, ReplaceMode::FirstOnly));
|
||||
range_pattern->end_range = TRY_OR_THROW_OOM(vm, range_pattern->end_range.replace("{0}"sv, pattern, ReplaceMode::FirstOnly));
|
||||
}
|
||||
|
||||
// FIXME: The above is not sufficient. For example, if the start date is days before the end date, and only the timeStyle
|
||||
|
@ -1146,22 +1153,22 @@ ThrowCompletionOr<Vector<PatternPartitionWithSource>> partition_date_time_range_
|
|||
}
|
||||
|
||||
// 11.5.11 FormatDateTimeRange ( dateTimeFormat, x, y ), https://tc39.es/ecma402/#sec-formatdatetimerange
|
||||
ThrowCompletionOr<DeprecatedString> format_date_time_range(VM& vm, DateTimeFormat& date_time_format, double start, double end)
|
||||
ThrowCompletionOr<String> format_date_time_range(VM& vm, DateTimeFormat& date_time_format, double start, double end)
|
||||
{
|
||||
// 1. Let parts be ? PartitionDateTimeRangePattern(dateTimeFormat, x, y).
|
||||
auto parts = TRY(partition_date_time_range_pattern(vm, date_time_format, start, end));
|
||||
|
||||
// 2. Let result be the empty String.
|
||||
StringBuilder result;
|
||||
ThrowableStringBuilder result(vm);
|
||||
|
||||
// 3. For each Record { [[Type]], [[Value]], [[Source]] } part in parts, do
|
||||
for (auto& part : parts) {
|
||||
// a. Set result to the string-concatenation of result and part.[[Value]].
|
||||
result.append(move(part.value));
|
||||
TRY(result.append(part.value));
|
||||
}
|
||||
|
||||
// 4. Return result.
|
||||
return result.build();
|
||||
return result.to_string();
|
||||
}
|
||||
|
||||
// 11.5.12 FormatDateTimeRangeToParts ( dateTimeFormat, x, y ), https://tc39.es/ecma402/#sec-formatdatetimerangetoparts
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2021-2022, Tim Flynn <trflynn89@serenityos.org>
|
||||
* Copyright (c) 2021-2023, Tim Flynn <trflynn89@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -7,7 +7,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <AK/Array.h>
|
||||
#include <AK/DeprecatedString.h>
|
||||
#include <AK/String.h>
|
||||
#include <AK/StringView.h>
|
||||
#include <AK/Time.h>
|
||||
|
@ -62,8 +61,8 @@ public:
|
|||
void set_hour_cycle(::Locale::HourCycle hour_cycle) { m_hour_cycle = hour_cycle; }
|
||||
void clear_hour_cycle() { m_hour_cycle.clear(); }
|
||||
|
||||
DeprecatedString const& time_zone() const { return m_time_zone; }
|
||||
void set_time_zone(DeprecatedString time_zone) { m_time_zone = move(time_zone); }
|
||||
String const& time_zone() const { return m_time_zone; }
|
||||
void set_time_zone(String time_zone) { m_time_zone = move(time_zone); }
|
||||
|
||||
bool has_date_style() const { return m_date_style.has_value(); }
|
||||
Style date_style() const { return *m_date_style; };
|
||||
|
@ -75,8 +74,8 @@ public:
|
|||
StringView time_style_string() const { return style_to_string(*m_time_style); };
|
||||
void set_time_style(StringView style) { m_time_style = style_from_string(style); };
|
||||
|
||||
DeprecatedString const& pattern() const { return Patterns::pattern; };
|
||||
void set_pattern(DeprecatedString pattern) { Patterns::pattern = move(pattern); }
|
||||
String const& pattern() const { return Patterns::pattern; };
|
||||
void set_pattern(String pattern) { Patterns::pattern = move(pattern); }
|
||||
|
||||
Span<::Locale::CalendarRangePattern const> range_patterns() const { return m_range_patterns.span(); };
|
||||
void set_range_patterns(Vector<::Locale::CalendarRangePattern> range_patterns) { m_range_patterns = move(range_patterns); }
|
||||
|
@ -139,7 +138,7 @@ private:
|
|||
String m_calendar; // [[Calendar]]
|
||||
String m_numbering_system; // [[NumberingSystem]]
|
||||
Optional<::Locale::HourCycle> m_hour_cycle; // [[HourCycle]]
|
||||
DeprecatedString m_time_zone; // [[TimeZone]]
|
||||
String m_time_zone; // [[TimeZone]]
|
||||
Optional<Style> m_date_style; // [[DateStyle]]
|
||||
Optional<Style> m_time_style; // [[TimeStyle]]
|
||||
Vector<::Locale::CalendarRangePattern> m_range_patterns; // [[RangePatterns]]
|
||||
|
@ -182,15 +181,15 @@ struct LocalTime {
|
|||
};
|
||||
|
||||
ThrowCompletionOr<Object*> to_date_time_options(VM&, Value options_value, OptionRequired, OptionDefaults);
|
||||
Optional<::Locale::CalendarPattern> date_time_style_format(StringView data_locale, DateTimeFormat& date_time_format);
|
||||
ThrowCompletionOr<Optional<::Locale::CalendarPattern>> date_time_style_format(VM&, StringView data_locale, DateTimeFormat& date_time_format);
|
||||
Optional<::Locale::CalendarPattern> basic_format_matcher(::Locale::CalendarPattern const& options, Vector<::Locale::CalendarPattern> formats);
|
||||
Optional<::Locale::CalendarPattern> best_fit_format_matcher(::Locale::CalendarPattern const& options, Vector<::Locale::CalendarPattern> formats);
|
||||
ThrowCompletionOr<Vector<PatternPartition>> format_date_time_pattern(VM&, DateTimeFormat&, Vector<PatternPartition> pattern_parts, double time, ::Locale::CalendarPattern const* range_format_options);
|
||||
ThrowCompletionOr<Vector<PatternPartition>> partition_date_time_pattern(VM&, DateTimeFormat&, double time);
|
||||
ThrowCompletionOr<DeprecatedString> format_date_time(VM&, DateTimeFormat&, double time);
|
||||
ThrowCompletionOr<String> format_date_time(VM&, DateTimeFormat&, double time);
|
||||
ThrowCompletionOr<Array*> format_date_time_to_parts(VM&, DateTimeFormat&, double time);
|
||||
ThrowCompletionOr<Vector<PatternPartitionWithSource>> partition_date_time_range_pattern(VM&, DateTimeFormat&, double start, double end);
|
||||
ThrowCompletionOr<DeprecatedString> format_date_time_range(VM&, DateTimeFormat&, double start, double end);
|
||||
ThrowCompletionOr<String> format_date_time_range(VM&, DateTimeFormat&, double start, double end);
|
||||
ThrowCompletionOr<Array*> format_date_time_range_to_parts(VM&, DateTimeFormat&, double start, double end);
|
||||
ThrowCompletionOr<LocalTime> to_local_time(VM&, Crypto::SignedBigInteger const& epoch_ns, StringView calendar, StringView time_zone);
|
||||
|
||||
|
|
|
@ -170,7 +170,7 @@ ThrowCompletionOr<DateTimeFormat*> initialize_date_time_format(VM& vm, DateTimeF
|
|||
|
||||
// Non-standard, default_hour_cycle will be empty if Unicode data generation is disabled.
|
||||
if (!default_hour_cycle.has_value()) {
|
||||
date_time_format.set_time_zone(default_time_zone());
|
||||
date_time_format.set_time_zone(TRY_OR_THROW_OOM(vm, String::from_utf8(default_time_zone())));
|
||||
return &date_time_format;
|
||||
}
|
||||
|
||||
|
@ -237,7 +237,7 @@ ThrowCompletionOr<DateTimeFormat*> initialize_date_time_format(VM& vm, DateTimeF
|
|||
}
|
||||
|
||||
// 32. Set dateTimeFormat.[[TimeZone]] to timeZone.
|
||||
date_time_format.set_time_zone(time_zone.to_deprecated_string());
|
||||
date_time_format.set_time_zone(move(time_zone));
|
||||
|
||||
// 33. Let formatOptions be a new Record.
|
||||
::Locale::CalendarPattern format_options {};
|
||||
|
@ -317,12 +317,12 @@ ThrowCompletionOr<DateTimeFormat*> initialize_date_time_format(VM& vm, DateTimeF
|
|||
|
||||
// b. Let styles be dataLocaleData.[[styles]].[[<resolvedCalendar>]].
|
||||
// c. Let bestFormat be DateTimeStyleFormat(dateStyle, timeStyle, styles).
|
||||
best_format = date_time_style_format(data_locale, date_time_format);
|
||||
best_format = MUST_OR_THROW_OOM(date_time_style_format(vm, data_locale, date_time_format));
|
||||
}
|
||||
// 43. Else,
|
||||
else {
|
||||
// a. Let formats be dataLocaleData.[[formats]].[[<resolvedCalendar>]].
|
||||
auto formats = ::Locale::get_calendar_available_formats(data_locale, date_time_format.calendar());
|
||||
auto formats = TRY_OR_THROW_OOM(vm, ::Locale::get_calendar_available_formats(data_locale, date_time_format.calendar()));
|
||||
|
||||
// b. If matcher is "basic", then
|
||||
if (TRY(matcher.as_string().utf8_string_view()) == "basic"sv) {
|
||||
|
@ -347,7 +347,7 @@ ThrowCompletionOr<DateTimeFormat*> initialize_date_time_format(VM& vm, DateTimeF
|
|||
}
|
||||
});
|
||||
|
||||
DeprecatedString pattern;
|
||||
String pattern;
|
||||
Vector<::Locale::CalendarRangePattern> range_patterns;
|
||||
|
||||
// 45. If dateTimeFormat.[[Hour]] is undefined, then
|
||||
|
@ -368,7 +368,7 @@ ThrowCompletionOr<DateTimeFormat*> initialize_date_time_format(VM& vm, DateTimeF
|
|||
}
|
||||
|
||||
// b. Let rangePatterns be bestFormat.[[rangePatterns12]].
|
||||
range_patterns = ::Locale::get_calendar_range12_formats(data_locale, date_time_format.calendar(), best_format->skeleton);
|
||||
range_patterns = TRY_OR_THROW_OOM(vm, ::Locale::get_calendar_range12_formats(data_locale, date_time_format.calendar(), best_format->skeleton));
|
||||
}
|
||||
// 47. Else,
|
||||
else {
|
||||
|
@ -376,7 +376,7 @@ ThrowCompletionOr<DateTimeFormat*> initialize_date_time_format(VM& vm, DateTimeF
|
|||
pattern = move(best_format->pattern);
|
||||
|
||||
// b. Let rangePatterns be bestFormat.[[rangePatterns]].
|
||||
range_patterns = ::Locale::get_calendar_range_formats(data_locale, date_time_format.calendar(), best_format->skeleton);
|
||||
range_patterns = TRY_OR_THROW_OOM(vm, ::Locale::get_calendar_range_formats(data_locale, date_time_format.calendar(), best_format->skeleton));
|
||||
}
|
||||
|
||||
// 48. Set dateTimeFormat.[[Pattern]] to pattern.
|
||||
|
|
|
@ -169,7 +169,7 @@ Optional<Weekday> get_locale_weekend_end(StringView locale)
|
|||
return find_regional_values_for_locale(locale, get_regional_weekend_end);
|
||||
}
|
||||
|
||||
DeprecatedString combine_skeletons(StringView first, StringView second)
|
||||
ErrorOr<String> combine_skeletons(StringView first, StringView second)
|
||||
{
|
||||
// https://unicode.org/reports/tr35/tr35-dates.html#availableFormats_appendItems
|
||||
constexpr auto field_order = Array {
|
||||
|
@ -207,14 +207,14 @@ DeprecatedString combine_skeletons(StringView first, StringView second)
|
|||
}
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
return builder.to_string();
|
||||
}
|
||||
|
||||
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>> __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> get_calendar_format(StringView locale, StringView calendar, CalendarFormatType type)
|
||||
ErrorOr<Optional<CalendarFormat>> get_calendar_format(StringView locale, StringView calendar, CalendarFormatType type)
|
||||
{
|
||||
switch (type) {
|
||||
case CalendarFormatType::Date:
|
||||
|
@ -228,10 +228,10 @@ Optional<CalendarFormat> get_calendar_format(StringView locale, StringView calen
|
|||
}
|
||||
}
|
||||
|
||||
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 {}; }
|
||||
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> {}; }
|
||||
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 {}; }
|
||||
|
@ -241,18 +241,18 @@ Optional<StringView> __attribute__((weak)) get_calendar_day_period_symbol_for_ho
|
|||
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 Optional<DeprecatedString> format_time_zone_offset(StringView locale, CalendarPatternStyle style, i64 offset_seconds)
|
||||
static ErrorOr<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 {};
|
||||
return OptionalNone {};
|
||||
|
||||
auto number_system = get_preferred_keyword_value_for_locale(locale, "nu"sv);
|
||||
if (!number_system.has_value())
|
||||
return {};
|
||||
return OptionalNone {};
|
||||
|
||||
if (offset_seconds == 0)
|
||||
return formats->gmt_zero_format;
|
||||
return 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;
|
||||
|
@ -290,16 +290,16 @@ static Optional<DeprecatedString> format_time_zone_offset(StringView locale, Cal
|
|||
}
|
||||
|
||||
// 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, builder.build()).release_value_but_fixme_should_propagate_errors();
|
||||
return formats->gmt_format.replace("{0}"sv, result, ReplaceMode::FirstOnly);
|
||||
auto result = TRY(replace_digits_for_number_system(*number_system, builder.build()));
|
||||
return TRY(String::from_utf8(formats->gmt_format)).replace("{0}"sv, result, ReplaceMode::FirstOnly);
|
||||
}
|
||||
|
||||
// https://unicode.org/reports/tr35/tr35-dates.html#Time_Zone_Format_Terminology
|
||||
DeprecatedString format_time_zone(StringView locale, StringView time_zone, CalendarPatternStyle style, AK::Time time)
|
||||
ErrorOr<String> format_time_zone(StringView locale, StringView time_zone, CalendarPatternStyle style, AK::Time time)
|
||||
{
|
||||
auto offset = TimeZone::get_time_zone_offset(time_zone, time);
|
||||
if (!offset.has_value())
|
||||
return time_zone;
|
||||
return String::from_utf8(time_zone);
|
||||
|
||||
switch (style) {
|
||||
case CalendarPatternStyle::Short:
|
||||
|
@ -307,12 +307,14 @@ DeprecatedString format_time_zone(StringView locale, StringView time_zone, Calen
|
|||
case CalendarPatternStyle::ShortGeneric:
|
||||
case CalendarPatternStyle::LongGeneric:
|
||||
if (auto name = get_time_zone_name(locale, time_zone, style, offset->in_dst); name.has_value())
|
||||
return *name;
|
||||
return String::from_utf8(*name);
|
||||
break;
|
||||
|
||||
case CalendarPatternStyle::ShortOffset:
|
||||
case CalendarPatternStyle::LongOffset:
|
||||
return format_time_zone_offset(locale, style, offset->seconds).value_or(time_zone);
|
||||
if (auto formatted_offset = TRY(format_time_zone_offset(locale, style, offset->seconds)); formatted_offset.has_value())
|
||||
return formatted_offset.release_value();
|
||||
return String::from_utf8(time_zone);
|
||||
|
||||
default:
|
||||
VERIFY_NOT_REACHED();
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
/*
|
||||
* Copyright (c) 2021-2022, Tim Flynn <trflynn89@serenityos.org>
|
||||
* Copyright (c) 2021-2023, Tim Flynn <trflynn89@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/DeprecatedString.h>
|
||||
#include <AK/Error.h>
|
||||
#include <AK/Optional.h>
|
||||
#include <AK/String.h>
|
||||
#include <AK/StringView.h>
|
||||
#include <AK/Time.h>
|
||||
#include <AK/Types.h>
|
||||
|
@ -111,9 +112,9 @@ struct CalendarPattern {
|
|||
callback(time_zone_name, other.time_zone_name, Field::TimeZoneName);
|
||||
}
|
||||
|
||||
DeprecatedString skeleton {};
|
||||
DeprecatedString pattern {};
|
||||
Optional<DeprecatedString> pattern12 {};
|
||||
String skeleton {};
|
||||
String pattern {};
|
||||
Optional<String> pattern12 {};
|
||||
Optional<HourCycle> hour_cycle {};
|
||||
|
||||
// https://unicode.org/reports/tr35/tr35-dates.html#Calendar_Fields
|
||||
|
@ -145,9 +146,9 @@ struct CalendarRangePattern : public CalendarPattern {
|
|||
};
|
||||
|
||||
Optional<Field> field {};
|
||||
DeprecatedString start_range {};
|
||||
String start_range {};
|
||||
StringView separator {};
|
||||
DeprecatedString end_range {};
|
||||
String end_range {};
|
||||
};
|
||||
|
||||
enum class CalendarFormatType : u8 {
|
||||
|
@ -208,16 +209,16 @@ Optional<WeekendEndRegion> weekend_end_region_from_string(StringView weekend_end
|
|||
Optional<Weekday> get_regional_weekend_end(StringView region);
|
||||
Optional<Weekday> get_locale_weekend_end(StringView region);
|
||||
|
||||
DeprecatedString combine_skeletons(StringView first, StringView second);
|
||||
ErrorOr<String> combine_skeletons(StringView first, StringView second);
|
||||
|
||||
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<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<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);
|
||||
|
@ -225,7 +226,7 @@ Optional<StringView> get_calendar_weekday_symbol(StringView locale, StringView c
|
|||
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);
|
||||
|
||||
DeprecatedString format_time_zone(StringView locale, StringView time_zone, CalendarPatternStyle style, AK::Time time);
|
||||
ErrorOr<String> format_time_zone(StringView locale, StringView time_zone, CalendarPatternStyle style, AK::Time 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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue