where dateStyle,timeStyle is not effective in Intl.DateTimeFormat

add dateStyle,timeStyle to simpleDateFormatIcu
issue:https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I87XK3

Signed-off-by: hecunmao <hecunmao@huawei.com>
Change-Id: Ia2ce83678e0c7636cc7f66217bc07dbfcec0a772
This commit is contained in:
hecunmao 2023-10-13 19:28:55 +08:00
parent 33f222201f
commit b60e7fcdc2
3 changed files with 169 additions and 0 deletions

View File

@ -647,4 +647,28 @@ HWTEST_F_L0(BuiltinsDateTimeFormatTest, DateTimeFormat_003)
JSHandle<TaggedArray> elements(thread, resultHandle->GetElements());
EXPECT_EQ(elements->GetLength(), 16U);
}
// DateTimeFormat_004
HWTEST_F_L0(BuiltinsDateTimeFormatTest, DateTimeFormat_004)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<JSTaggedValue> localesString(factory->NewFromASCII("zh-CN"));
auto jsObj = JSHandle<JSObject>(thread, JSDateTimeFormatForObj_002(thread));
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
JSHandle<JSTaggedValue> fullValue(factory->NewFromASCII("full"));
JSHandle<JSTaggedValue> falseValue(thread, JSTaggedValue(false));
JSHandle<JSTaggedValue> dateStyleValue(factory->NewFromASCII("dateStyle"));
JSHandle<JSTaggedValue> timeStyleeValue(factory->NewFromASCII("timeStyle"));
JSHandle<JSTaggedValue> hour12Value(factory->NewFromASCII("hour12"));
JSObject::SetProperty(thread, optionsObj, dateStyleValue, fullValue);
JSObject::SetProperty(thread, optionsObj, timeStyleeValue, fullValue);
JSObject::SetProperty(thread, optionsObj, hour12Value, falseValue);
auto constructorResult = JSDateTimeFormatConstructor(thread, optionsObj, localesString);
JSHandle<EcmaString> resultStr =
JSDateTimeFormat::FormatDateTime(thread, JSHandle<JSDateTimeFormat>(thread, constructorResult), 0.0);
EXPECT_STREQ("1970年1月1日星期四 中国标准时间 08:00:00", EcmaStringAccessor(resultStr).ToCString().c_str());
}
} // namespace panda::test

View File

@ -189,6 +189,134 @@ JSHandle<EcmaString> JSDateTimeFormat::ToValueString(JSThread *thread, const Val
return result;
}
icu::DateFormat::EStyle DateTimeStyleToEStyle(DateTimeStyleOption style)
{
switch (style) {
case DateTimeStyleOption::FULL: {
return icu::DateFormat::kFull;
}
case DateTimeStyleOption::LONG: {
return icu::DateFormat::kLong;
}
case DateTimeStyleOption::MEDIUM: {
return icu::DateFormat::kMedium;
}
case DateTimeStyleOption::SHORT: {
return icu::DateFormat::kShort;
}
case DateTimeStyleOption::UNDEFINED: {
return icu::DateFormat::kNone;
}
default: {
return icu::DateFormat::kNone;
}
}
}
HourCycleOption HourCycleFromPattern(const icu::UnicodeString pattern)
{
bool inQuote = false;
for (int32_t i = 0; i < pattern.length(); i++) {
char16_t ch = pattern[i];
switch (ch) {
case '\'':
inQuote = !inQuote;
break;
case 'K':
if (!inQuote) {
return HourCycleOption::H11;
}
break;
case 'h':
if (!inQuote) {
return HourCycleOption::H12;
}
break;
case 'H':
if (!inQuote) {
return HourCycleOption::H23;
}
break;
case 'k':
if (!inQuote) {
return HourCycleOption::H24;
}
break;
default : {
break;
}
}
}
return HourCycleOption::UNDEFINED;
}
icu::UnicodeString ReplaceSkeleton(const icu::UnicodeString input, HourCycleOption hc)
{
icu::UnicodeString result;
char16_t to;
switch (hc) {
case HourCycleOption::H11:
to = 'K';
break;
case HourCycleOption::H12:
to = 'h';
break;
case HourCycleOption::H23:
to = 'H';
break;
case HourCycleOption::H24:
to = 'k';
break;
default:
UNREACHABLE();
break;
}
int inputLength = input.length();
for (int32_t i = 0; i < inputLength; ++i) {
switch (input[i]) {
case 'a':
case 'b':
case 'B':
break;
case 'h':
case 'H':
case 'k':
case 'K':
result += to;
break;
default:
result += input[i];
break;
}
}
return result;
}
std::unique_ptr<icu::SimpleDateFormat> DateTimeStylePattern(DateTimeStyleOption dateStyle,
DateTimeStyleOption timeStyle,
icu::Locale &icuLocale,
HourCycleOption hc,
icu::DateTimePatternGenerator *generator)
{
std::unique_ptr<icu::SimpleDateFormat> result;
icu::DateFormat::EStyle icuDateStyle = DateTimeStyleToEStyle(dateStyle);
icu::DateFormat::EStyle icuTimeStyle = DateTimeStyleToEStyle(timeStyle);
result.reset(reinterpret_cast<icu::SimpleDateFormat *>(
icu::DateFormat::createDateTimeInstance(icuDateStyle, icuTimeStyle, icuLocale)));
UErrorCode status = U_ZERO_ERROR;
icu::UnicodeString pattern;
pattern = result->toPattern(pattern);
icu::UnicodeString skeleton = icu::DateTimePatternGenerator::staticGetSkeleton(pattern, status);
ASSERT_PRINT(U_SUCCESS(status), "staticGetSkeleton failed");
if (hc == HourCycleFromPattern(pattern)) {
return result;
}
skeleton = ReplaceSkeleton(skeleton, hc);
pattern = generator->getBestPattern(skeleton, UDATPG_MATCH_HOUR_FIELD_LENGTH, status);
result = std::make_unique<icu::SimpleDateFormat>(pattern, icuLocale, status);
return result;
}
// 13.1.1 InitializeDateTimeFormat (dateTimeFormat, locales, options)
// NOLINTNEXTLINE(readability-function-size)
JSHandle<JSDateTimeFormat> JSDateTimeFormat::InitializeDateTimeFormat(JSThread *thread,
@ -379,6 +507,7 @@ JSHandle<JSDateTimeFormat> JSDateTimeFormat::InitializeDateTimeFormat(JSThread *
// c. Set opt.[[<prop>]] to value.
std::string skeleton;
std::vector<IcuPatternDesc> data = GetIcuPatternDesc(hc);
int32_t explicitFormatComponents = 0;
for (const IcuPatternDesc &item : data) {
// prop be [[TimeZoneName]]
if (item.property == "timeZoneName") {
@ -392,6 +521,7 @@ JSHandle<JSDateTimeFormat> JSDateTimeFormat::InitializeDateTimeFormat(JSThread *
bool isFind = JSLocale::GetOptionOfString(thread, dateTimeOptions, property, item.allowedValues, &value);
RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSDateTimeFormat, thread);
if (isFind) {
explicitFormatComponents = 1;
skeleton += item.map.find(value)->second;
// [[Hour]] is defined.
isHourDefined = (item.property == "hour") ? true : isHourDefined;
@ -449,6 +579,13 @@ JSHandle<JSDateTimeFormat> JSDateTimeFormat::InitializeDateTimeFormat(JSThread *
generator.get()->getBestPattern(dtfSkeleton, UDATPG_MATCH_HOUR_FIELD_LENGTH, status), dtfHourCycle);
ASSERT_PRINT((U_SUCCESS(status) != 0), "get best pattern failed");
auto simpleDateFormatIcu(std::make_unique<icu::SimpleDateFormat>(pattern, icuLocale, status));
if (dateStyle != DateTimeStyleOption::UNDEFINED || timeStyle != DateTimeStyleOption::UNDEFINED) {
if (explicitFormatComponents != 0) {
THROW_TYPE_ERROR_AND_RETURN(thread, "Invalid option : option", dateTimeFormat);
}
simpleDateFormatIcu = DateTimeStylePattern(dateStyle, timeStyle, icuLocale,
hc, generator.get());
}
if (U_FAILURE(status) != 0) {
simpleDateFormatIcu = std::unique_ptr<icu::SimpleDateFormat>();
}

View File

@ -42,6 +42,14 @@ class IcuPatternDesc;
std::vector<IcuPatternDesc> BuildIcuPatternDescs();
std::vector<IcuPatternDesc> InitializePattern(const IcuPatternDesc &hourData);
icu::DateFormat::EStyle DateTimeStyleToEStyle(DateTimeStyleOption style);
HourCycleOption HourCycleFromPattern(const icu::UnicodeString pattern);
icu::UnicodeString ReplaceSkeleton(const icu::UnicodeString input, HourCycleOption hc);
std::unique_ptr<icu::SimpleDateFormat> DateTimeStylePattern(DateTimeStyleOption dateStyle,
DateTimeStyleOption timeStyle,
icu::Locale &icuLocale,
HourCycleOption hc,
icu::DateTimePatternGenerator *generator);
using IcuPatternDescVect = std::vector<IcuPatternDesc>;
using IcuPatternEntry = std::pair<std::string, std::string>;