LibUnicode: Use a calendar with icu4x glue to format lunisolar calendars

Commit 86c8a57794 caused one regression in
test/intl402/DateTimeFormat. It is expected that Intl.DateTimeFormat and
Temporal produce consistent results.

Due to the píngqì approximation implemented in icu4x, it actually does
not totally align with icu4c for lunisolar calendars at extreme dates.
Ideally, icu4x will one day support all Intl.DateTimeFormat operations
as well. But for now, the fix is to create a custom icu::Calendar class
for lunisolar calendars that pipes calculations to icu4x.
This commit is contained in:
Timothy Flynn
2026-03-12 09:35:36 -04:00
committed by Andreas Kling
parent 101fee6cb2
commit ef899027c5
Notes: github-actions[bot] 2026-03-12 22:30:55 +00:00
8 changed files with 382 additions and 1 deletions

View File

@@ -7,8 +7,10 @@
#include <AK/AllOf.h>
#include <AK/Array.h>
#include <AK/GenericLexer.h>
#include <AK/GenericShorthands.h>
#include <AK/StringBuilder.h>
#include <AK/TypeCasts.h>
#include <LibUnicode/ChineseDangiCalendar.h>
#include <LibUnicode/DateTimeFormat.h>
#include <LibUnicode/ICU.h>
#include <LibUnicode/Locale.h>
@@ -628,7 +630,10 @@ static void apply_time_zone_to_formatter(icu::SimpleDateFormat& formatter, icu::
auto* calendar = icu::Calendar::createInstance(time_zone_data->time_zone(), locale, status);
verify_icu_success(status);
if (auto* gregorian_calendar = as_if<icu::GregorianCalendar>(*calendar)) {
if (auto const* calendar_type = calendar->getType(); first_is_one_of(calendar_type, "chinese"sv, "dangi"sv)) {
calendar = new ChineseDangiCalendar(adopt_own(*calendar), locale, status);
verify_icu_success(status);
} else if (auto* gregorian_calendar = as_if<icu::GregorianCalendar>(*calendar)) {
// https://tc39.es/ecma262/#sec-time-values-and-time-range
// A time value supports a slightly smaller range of -8,640,000,000,000,000 to 8,640,000,000,000,000 milliseconds.
static constexpr double ECMA_262_MINIMUM_TIME = -8.64E15;