mirror of
https://github.com/Samsung/escargot.git
synced 2026-06-22 10:01:50 +00:00
Impelement Intl.DateTimeFormat.prototype.formatRange
Signed-off-by: Seonghyun Kim <sh8281.kim@samsung.com>
This commit is contained in:
parent
2e33b02111
commit
05553d2264
12 changed files with 294 additions and 32 deletions
|
|
@ -288,7 +288,8 @@ extern "C" {
|
|||
#include "RuntimeICUBinder.h"
|
||||
#include "ICUPolyfill.h"
|
||||
#else
|
||||
|
||||
#define U_SHOW_CPLUSPLUS_API 0
|
||||
#define U_SHOW_CPLUSPLUS_HEADER_API 0
|
||||
#if defined(OS_WINDOWS)
|
||||
#include <icu.h>
|
||||
#else
|
||||
|
|
@ -313,6 +314,8 @@ extern "C" {
|
|||
#include <unicode/uloc.h> // for Intl
|
||||
#include <unicode/uldnames.h> // for Intl
|
||||
#include <unicode/ulistformatter.h> // for Intl
|
||||
#include <unicode/ures.h> // for Intl
|
||||
#include <unicode/udateintervalformat.h> // for Intl
|
||||
|
||||
// FIXME replace these vzone decl into include
|
||||
// I declare vzone api because there is no header file in include folder
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ static Value builtinDateConstructor(ExecutionState& state, Value thisValue, size
|
|||
} else {
|
||||
// Let tv be ToNumber(v).
|
||||
double V = v.toNumber(state);
|
||||
thisObject->setTimeValue(DateObject::timeClip(state, V));
|
||||
thisObject->setTimeValue(DateObject::timeClipToTime64(state, V));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -320,7 +320,7 @@ static Value builtinDateSetHelper(ExecutionState& state, DateSetterType setterTy
|
|||
if (setterType == DateSetterType::Day && length == 3) {
|
||||
// setFullYear, setUTCFullYear case
|
||||
if (!isOriginalDateValid) {
|
||||
d->setTimeValue(DateObject::timeClip(state, 0));
|
||||
d->setTimeValue(DateObject::timeClipToTime64(state, 0));
|
||||
d->setTimeValue(d->getTimezoneOffset(state) * TimeConstant::MsPerMinute);
|
||||
originalDateValue = d->primitiveValue();
|
||||
isOriginalDateValid = true;
|
||||
|
|
@ -409,7 +409,7 @@ static Value builtinDateSetTime(ExecutionState& state, Value thisValue, size_t a
|
|||
{
|
||||
RESOLVE_THIS_BINDING_TO_DATE(thisObject, Date, setTime);
|
||||
if (argc > 0) {
|
||||
thisObject->setTimeValue(DateObject::timeClip(state, argv[0].toNumber(state)));
|
||||
thisObject->setTimeValue(DateObject::timeClipToTime64(state, argv[0].toNumber(state)));
|
||||
return Value(Value::DoubleToIntConvertibleTestNeeds, thisObject->primitiveValue());
|
||||
} else {
|
||||
thisObject->setTimeValueAsNaN();
|
||||
|
|
@ -433,7 +433,7 @@ static Value builtinDateSetYear(ExecutionState& state, Value thisValue, size_t a
|
|||
DateObject* d = thisObject;
|
||||
|
||||
if (!(d->isValid())) {
|
||||
d->setTimeValue(DateObject::timeClip(state, 0));
|
||||
d->setTimeValue(DateObject::timeClipToTime64(state, 0));
|
||||
d->setTimeValue(d->getTimezoneOffset(state) * TimeConstant::MsPerMinute);
|
||||
}
|
||||
ASSERT(d->isValid());
|
||||
|
|
|
|||
|
|
@ -248,6 +248,23 @@ static Value builtinIntlDateTimeFormatFormatToParts(ExecutionState& state, Value
|
|||
return dtf->formatToParts(state, x);
|
||||
}
|
||||
|
||||
static Value builtinIntlDateTimeFormatFormatRange(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
|
||||
{
|
||||
if (!thisValue.isObject() || !thisValue.asObject()->isIntlDateTimeFormatObject()) {
|
||||
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, "Method called on incompatible receiver");
|
||||
}
|
||||
|
||||
if (argv[0].isUndefined() || argv[1].isUndefined()) {
|
||||
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, "get invalid date value");
|
||||
}
|
||||
|
||||
IntlDateTimeFormatObject* dtf = thisValue.asObject()->asIntlDateTimeFormatObject();
|
||||
double x = argv[0].toNumber(state);
|
||||
double y = argv[1].toNumber(state);
|
||||
auto result = dtf->formatRange(state, x, y);
|
||||
return Value(new UTF16String(result.data(), result.length()));
|
||||
}
|
||||
|
||||
static void setFormatOpt(ExecutionState& state, Object* internalSlot, Object* result, String* prop)
|
||||
{
|
||||
ObjectGetResult r;
|
||||
|
|
@ -1479,6 +1496,9 @@ void GlobalObject::installIntl(ExecutionState& state)
|
|||
m_intlDateTimeFormatPrototype->directDefineOwnProperty(state, state.context()->staticStrings().lazyFormatToParts(),
|
||||
ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->lazyFormatToParts(), builtinIntlDateTimeFormatFormatToParts, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
|
||||
|
||||
m_intlDateTimeFormatPrototype->directDefineOwnProperty(state, state.context()->staticStrings().lazyFormatRange(),
|
||||
ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->lazyFormatRange(), builtinIntlDateTimeFormatFormatRange, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
|
||||
|
||||
m_intlDateTimeFormatPrototype->directDefineOwnProperty(state, state.context()->staticStrings().resolvedOptions,
|
||||
ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->resolvedOptions, builtinIntlDateTimeFormatResolvedOptions, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
|
||||
|
||||
|
|
|
|||
|
|
@ -491,6 +491,7 @@ IntlDateTimeFormatObject::IntlDateTimeFormatObject(ExecutionState& state, Object
|
|||
, m_calendar(String::emptyString())
|
||||
, m_numberingSystem(String::emptyString())
|
||||
, m_timeZone(String::emptyString())
|
||||
, m_timeZoneICU(String::emptyString())
|
||||
, m_icuDateFormat(nullptr)
|
||||
{
|
||||
// Let requestedLocales be ? CanonicalizeLocaleList(locales).
|
||||
|
|
@ -1026,7 +1027,9 @@ void IntlDateTimeFormatObject::initDateTimeFormatOtherHelper(ExecutionState& sta
|
|||
+ pad('0', 2, std::to_string(absMinutes / 60)) + pad('0', 2, std::to_string(absMinutes % 60));
|
||||
timeZoneView = utf8StringToUTF16String(timeZoneForICU.data(), timeZoneForICU.length());
|
||||
}
|
||||
m_icuDateFormat = udat_open(UDAT_PATTERN, UDAT_PATTERN, dataLocaleWithExtensions.data(), (UChar*)timeZoneView.data(), timeZoneView.length(), (UChar*)patternBuffer.data(), patternBuffer.length(), &status);
|
||||
m_timeZoneICU = new UTF16String(std::move(timeZoneView));
|
||||
m_icuDateFormat = udat_open(UDAT_PATTERN, UDAT_PATTERN, dataLocaleWithExtensions.data(), m_timeZoneICU->bufferAccessData().bufferAs16Bit,
|
||||
m_timeZoneICU->length(), (UChar*)patternBuffer.data(), patternBuffer.length(), &status);
|
||||
if (U_FAILURE(status)) {
|
||||
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, "failed to initialize DateTimeFormat");
|
||||
return;
|
||||
|
|
@ -1035,6 +1038,9 @@ void IntlDateTimeFormatObject::initDateTimeFormatOtherHelper(ExecutionState& sta
|
|||
addFinalizer([](PointerValue* obj, void* data) {
|
||||
IntlDateTimeFormatObject* self = (IntlDateTimeFormatObject*)obj;
|
||||
udat_close(self->m_icuDateFormat);
|
||||
if (self->m_icuDateIntervalFormat) {
|
||||
udtitvfmt_close(self->m_icuDateIntervalFormat.value());
|
||||
}
|
||||
},
|
||||
nullptr);
|
||||
|
||||
|
|
@ -1404,5 +1410,198 @@ Value IntlDateTimeFormatObject::toDateTimeOptions(ExecutionState& state, Value o
|
|||
return options;
|
||||
}
|
||||
|
||||
void IntlDateTimeFormatObject::initICUIntervalFormatIfNecessary(ExecutionState& state)
|
||||
{
|
||||
if (m_icuDateIntervalFormat) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto toPatternResult = INTL_ICU_STRING_BUFFER_OPERATION(udat_toPattern, m_icuDateFormat, false);
|
||||
if (U_FAILURE(toPatternResult.first)) {
|
||||
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, "failed to initialize DateIntervalFormat");
|
||||
return;
|
||||
}
|
||||
auto pattern(std::move(toPatternResult.second));
|
||||
|
||||
auto getSkeletonResult = INTL_ICU_STRING_BUFFER_OPERATION(udatpg_getSkeleton, nullptr, pattern.data(), pattern.size());
|
||||
if (U_FAILURE(getSkeletonResult.first)) {
|
||||
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, "failed to initialize DateIntervalFormat");
|
||||
return;
|
||||
}
|
||||
auto skeleton(std::move(getSkeletonResult.second));
|
||||
|
||||
// While the pattern is including right HourCycle patterns, UDateIntervalFormat does not follow.
|
||||
// We need to enforce HourCycle by setting "hc" extension if it is specified.
|
||||
std::string locale = m_locale->toNonGCUTF8StringData();
|
||||
locale += "-u-ca-";
|
||||
locale += m_calendar->asString()->toNonGCUTF8StringData();
|
||||
locale += "-nu-";
|
||||
locale += m_numberingSystem->asString()->toNonGCUTF8StringData();
|
||||
if (!m_hourCycle.toValue().isUndefined()) {
|
||||
locale += "-hc-";
|
||||
locale += m_hourCycle.toValue().asString()->toNonGCUTF8StringData();
|
||||
}
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
m_icuDateIntervalFormat = udtitvfmt_open(locale.data(), skeleton.data(), skeleton.size(), m_timeZoneICU->bufferAccessData().bufferAs16Bit, m_timeZoneICU->length(), &status);
|
||||
if (U_FAILURE(status)) {
|
||||
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, "failed to initialize DateIntervalFormat");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static LocalResourcePointer<UFormattedDateInterval> formattedValueFromDateRange(ExecutionState& state, UDateIntervalFormat* dateIntervalFormat,
|
||||
UDateFormat* dateFormat, double startDate, double endDate, UErrorCode& status)
|
||||
{
|
||||
#if defined(ENABLE_RUNTIME_ICU_BINDER)
|
||||
UVersionInfo versionArray;
|
||||
u_getVersion(versionArray);
|
||||
if (versionArray[0] < 67) {
|
||||
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, "some function of Intl.DateTimeFormat needs 67+ version of ICU");
|
||||
}
|
||||
#endif
|
||||
|
||||
LocalResourcePointer<UFormattedDateInterval> result(udtitvfmt_openResult(&status),
|
||||
[](UFormattedDateInterval* d) { udtitvfmt_closeResult(d); });
|
||||
if (U_FAILURE(status)) {
|
||||
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, "failed to format DateIntervalFormat");
|
||||
return result;
|
||||
}
|
||||
|
||||
// If a date is after Oct 15, 1582, the configuration of gregorian calendar change date in UCalendar does not affect
|
||||
// on the formatted string. To ensure that it is after Oct 15 in all timezones, we add one day to gregorian calendar
|
||||
// change date in UTC, so that this check can conservatively answer whether the date is definitely after gregorian
|
||||
// calendar change date.
|
||||
auto definitelyAfterGregorianCalendarChangeDate = [](double millisecondsFromEpoch) {
|
||||
constexpr double gregorianCalendarReformDateInUTC = -12219292800000.0;
|
||||
return millisecondsFromEpoch >= (gregorianCalendarReformDateInUTC + TimeConstant::MsPerDay);
|
||||
};
|
||||
|
||||
// UFormattedDateInterval does not have a way to configure gregorian calendar change date while ECMAScript requires that
|
||||
// gregorian calendar change should not have effect (we are setting ucal_setGregorianChange(cal, minECMAScriptTime, &status) explicitly).
|
||||
// As a result, if the input date is older than gregorian calendar change date (Oct 15, 1582), the formatted string becomes
|
||||
// julian calendar date.
|
||||
// udtitvfmt_formatCalendarToResult API offers the way to set calendar to each date of the input, so that we can use UDateFormat's
|
||||
// calendar which is already configured to meet ECMAScript's requirement (effectively clearing gregorian calendar change date).
|
||||
//
|
||||
// If we can ensure that startDate is after gregorian calendar change date, we can just use udtitvfmt_formatToResult since gregorian
|
||||
// calendar change date does not affect on the formatted string.
|
||||
//
|
||||
// https://unicode-org.atlassian.net/browse/ICU-20705
|
||||
if (definitelyAfterGregorianCalendarChangeDate(startDate)) {
|
||||
udtitvfmt_formatToResult(dateIntervalFormat, startDate, endDate, result.get(), &status);
|
||||
} else {
|
||||
auto createCalendarForDate = [](const UCalendar* calendar, double date, UErrorCode& status) -> LocalResourcePointer<UCalendar> {
|
||||
auto result = LocalResourcePointer<UCalendar>(ucal_clone(calendar, &status), [](UCalendar* cal) {
|
||||
ucal_close(cal);
|
||||
});
|
||||
if (U_FAILURE(status)) {
|
||||
result.reset();
|
||||
return result;
|
||||
}
|
||||
ucal_setMillis(result.get(), date, &status);
|
||||
if (U_FAILURE(status)) {
|
||||
result.reset();
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
auto calendar = udat_getCalendar(dateFormat);
|
||||
|
||||
auto startCalendar = createCalendarForDate(calendar, startDate, status);
|
||||
if (U_FAILURE(status)) {
|
||||
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, "failed to format DateIntervalFormat");
|
||||
return result;
|
||||
}
|
||||
|
||||
auto endCalendar = createCalendarForDate(calendar, endDate, status);
|
||||
if (U_FAILURE(status)) {
|
||||
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, "failed to format DateIntervalFormat");
|
||||
return result;
|
||||
}
|
||||
|
||||
udtitvfmt_formatCalendarToResult(dateIntervalFormat, startCalendar.get(), endCalendar.get(), result.get(), &status);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool dateFieldsPracticallyEqual(const UFormattedValue* formattedValue, UErrorCode& status)
|
||||
{
|
||||
LocalResourcePointer<UConstrainedFieldPosition> iterator(ucfpos_open(&status), [](UConstrainedFieldPosition* pos) {
|
||||
ucfpos_close(pos);
|
||||
});
|
||||
|
||||
if (U_FAILURE(status)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We only care about UFIELD_CATEGORY_DATE_INTERVAL_SPAN category.
|
||||
ucfpos_constrainCategory(iterator.get(), UFIELD_CATEGORY_DATE_INTERVAL_SPAN, &status);
|
||||
if (U_FAILURE(status)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool hasSpan = ufmtval_nextPosition(formattedValue, iterator.get(), &status);
|
||||
if (U_FAILURE(status)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !hasSpan;
|
||||
}
|
||||
|
||||
UTF16StringDataNonGCStd IntlDateTimeFormatObject::formatRange(ExecutionState& state, double startDate, double endDate)
|
||||
{
|
||||
startDate = DateObject::timeClip(startDate);
|
||||
endDate = DateObject::timeClip(endDate);
|
||||
|
||||
if (std::isnan(startDate) || std::isnan(endDate)) {
|
||||
ErrorObject::throwBuiltinError(state, ErrorCode::RangeError, "get invalid date value");
|
||||
}
|
||||
|
||||
initICUIntervalFormatIfNecessary(state);
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
auto result = formattedValueFromDateRange(state, m_icuDateIntervalFormat.value(), m_icuDateFormat, startDate, endDate, status);
|
||||
if (U_FAILURE(status)) {
|
||||
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, "failed to format DateIntervalFormat");
|
||||
return UTF16StringDataNonGCStd();
|
||||
}
|
||||
|
||||
// UFormattedValue is owned by UFormattedDateInterval. We do not need to close it.
|
||||
auto formattedValue = udtitvfmt_resultAsValue(result.get(), &status);
|
||||
if (U_FAILURE(status)) {
|
||||
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, "failed to format DateIntervalFormat");
|
||||
return UTF16StringDataNonGCStd();
|
||||
}
|
||||
|
||||
// If the formatted parts of startDate and endDate are the same, it is possible that the resulted string does not look like range.
|
||||
// For example, if the requested format only includes "year" and startDate and endDate are the same year, the result just contains one year.
|
||||
// In that case, startDate and endDate are *practically-equal* (spec term), and we generate parts as we call `formatToParts(startDate)` with
|
||||
// `source: "shared"` additional fields.
|
||||
bool equal = dateFieldsPracticallyEqual(formattedValue, status);
|
||||
if (U_FAILURE(status)) {
|
||||
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, "failed to format DateIntervalFormat");
|
||||
return UTF16StringDataNonGCStd();
|
||||
}
|
||||
|
||||
if (equal) {
|
||||
return format(state, startDate);
|
||||
}
|
||||
|
||||
int32_t formattedStringLength = 0;
|
||||
const UChar* formattedStringPointer = ufmtval_getString(formattedValue, &formattedStringLength, &status);
|
||||
if (U_FAILURE(status)) {
|
||||
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, "failed to format DateIntervalFormat");
|
||||
return UTF16StringDataNonGCStd();
|
||||
}
|
||||
|
||||
UTF16StringDataNonGCStd buffer(formattedStringPointer, formattedStringLength);
|
||||
replaceNarrowNoBreakSpaceOrThinSpaceWithNormalSpace(buffer);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
} // namespace Escargot
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ public:
|
|||
|
||||
UTF16StringDataNonGCStd format(ExecutionState& state, double x);
|
||||
ArrayObject* formatToParts(ExecutionState& state, double x);
|
||||
UTF16StringDataNonGCStd formatRange(ExecutionState& state, double startDate, double endDate);
|
||||
static Value toDateTimeOptions(ExecutionState& state, Value options, Value required, Value defaults);
|
||||
static std::string readHourCycleFromPattern(const UTF16StringDataNonGCStd& patternString);
|
||||
String* locale() const
|
||||
|
|
@ -139,11 +140,12 @@ protected:
|
|||
String* initDateTimeFormatMainHelper(ExecutionState& state, StringMap& opt, const Value& options, const Value& hour12, std::function<void(String* prop, Value* values, size_t valuesSize)>& doTable4, StringBuilder& skeletonBuilder);
|
||||
void initDateTimeFormatOtherHelper(ExecutionState& state, const Value& dataLocale, const Value& dateStyle, const Value& timeStyle, const Value& hourCycle, const Value& hour12, String* hour, const StringMap& opt, std::string& dataLocaleWithExtensions, StringBuilder& skeletonBuilder);
|
||||
void setDateFromPattern(ExecutionState& state, UTF16StringDataNonGCStd& patternBuffer, bool hasHourOption);
|
||||
|
||||
void initICUIntervalFormatIfNecessary(ExecutionState& state);
|
||||
String* m_locale;
|
||||
String* m_calendar;
|
||||
String* m_numberingSystem;
|
||||
String* m_timeZone;
|
||||
String* m_timeZoneICU;
|
||||
|
||||
EncodedValue m_hour12;
|
||||
EncodedValue m_era;
|
||||
|
|
@ -162,6 +164,7 @@ protected:
|
|||
EncodedValue m_timeStyle;
|
||||
|
||||
UDateFormat* m_icuDateFormat;
|
||||
Optional<UDateIntervalFormat*> m_icuDateIntervalFormat;
|
||||
};
|
||||
|
||||
} // namespace Escargot
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ void DateObject::setTimeValue(ExecutionState& state, const Value& v)
|
|||
{
|
||||
Value pv = v.toPrimitive(state);
|
||||
if (pv.isNumber()) {
|
||||
setTimeValue(DateObject::timeClip(state, pv.asNumber()));
|
||||
setTimeValue(DateObject::timeClipToTime64(state, pv.asNumber()));
|
||||
} else {
|
||||
String* istr = v.toString(state);
|
||||
setTimeValue(parseStringToDate(state, istr));
|
||||
|
|
|
|||
|
|
@ -79,7 +79,15 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
static time64_t timeClip(ExecutionState& state, double V)
|
||||
static double timeClip(double t)
|
||||
{
|
||||
if (std::abs(t) > TimeConstant::MaximumDatePrimitiveValue) {
|
||||
return std::numeric_limits<double>::quiet_NaN();
|
||||
}
|
||||
return std::trunc(t) + 0.0;
|
||||
}
|
||||
|
||||
static time64_t timeClipToTime64(ExecutionState& state, double V)
|
||||
{
|
||||
if (std::isinf(V) || std::isnan(V)) {
|
||||
return TIME64NAN;
|
||||
|
|
|
|||
|
|
@ -527,13 +527,23 @@ static std::string findTimezone()
|
|||
#else
|
||||
static std::string findTimezone()
|
||||
{
|
||||
auto tz = icu::TimeZone::detectHostTimeZone();
|
||||
icu::UnicodeString id;
|
||||
tz->getID(id);
|
||||
delete tz;
|
||||
std::string r;
|
||||
id.toUTF8String(r);
|
||||
return r;
|
||||
UChar result[256];
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
int32_t len = ucal_getHostTimeZone(result, sizeof(result) / sizeof(UChar), &status);
|
||||
if (U_SUCCESS(status)) {
|
||||
std::string u8Result;
|
||||
for (int32_t i = 0; i < len; i++) {
|
||||
u8Result.push_back(result[i]);
|
||||
}
|
||||
return u8Result;
|
||||
}
|
||||
|
||||
// fallback
|
||||
time_t t;
|
||||
tm lt;
|
||||
t = time(NULL);
|
||||
localtime_r(&t, <);
|
||||
return lt.tm_zone;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
9
third_party/runtime_icu_binder/ICUPolyfill.h
vendored
9
third_party/runtime_icu_binder/ICUPolyfill.h
vendored
|
|
@ -130,6 +130,7 @@
|
|||
#define ucal_getDayOfWeekType RuntimeICUBinder::ICU::instance().ucal_getDayOfWeekType
|
||||
#define ucal_setGregorianChange RuntimeICUBinder::ICU::instance().ucal_setGregorianChange
|
||||
#define ucal_setMillis RuntimeICUBinder::ICU::instance().ucal_setMillis
|
||||
#define ucal_clone RuntimeICUBinder::ICU::instance().ucal_clone
|
||||
|
||||
#define udatpg_close RuntimeICUBinder::ICU::instance().udatpg_close
|
||||
#define udatpg_open RuntimeICUBinder::ICU::instance().udatpg_open
|
||||
|
|
@ -262,4 +263,12 @@
|
|||
#define ulistfmt_resultAsValue RuntimeICUBinder::ICU::instance().ulistfmt_resultAsValue
|
||||
#define ulistfmt_closeResult RuntimeICUBinder::ICU::instance().ulistfmt_closeResult
|
||||
|
||||
#define udtitvfmt_open RuntimeICUBinder::ICU::instance().udtitvfmt_open
|
||||
#define udtitvfmt_openResult RuntimeICUBinder::ICU::instance().udtitvfmt_openResult
|
||||
#define udtitvfmt_close RuntimeICUBinder::ICU::instance().udtitvfmt_close
|
||||
#define udtitvfmt_closeResult RuntimeICUBinder::ICU::instance().udtitvfmt_closeResult
|
||||
#define udtitvfmt_formatToResult RuntimeICUBinder::ICU::instance().udtitvfmt_formatToResult
|
||||
#define udtitvfmt_formatCalendarToResult RuntimeICUBinder::ICU::instance().udtitvfmt_formatCalendarToResult
|
||||
#define udtitvfmt_resultAsValue RuntimeICUBinder::ICU::instance().udtitvfmt_resultAsValue
|
||||
|
||||
#endif
|
||||
|
|
|
|||
16
third_party/runtime_icu_binder/ICUTypes.h
vendored
16
third_party/runtime_icu_binder/ICUTypes.h
vendored
|
|
@ -8411,6 +8411,22 @@ typedef enum UListFormatterWidth {
|
|||
} UListFormatterWidth;
|
||||
#endif /* U_HIDE_DRAFT_API */
|
||||
|
||||
// udateintervalformat.h
|
||||
|
||||
/**
|
||||
* Opaque UDateIntervalFormat object for use in C programs.
|
||||
* @stable ICU 4.8
|
||||
*/
|
||||
struct UDateIntervalFormat;
|
||||
typedef struct UDateIntervalFormat UDateIntervalFormat; /**< C typedef for struct UDateIntervalFormat. @stable ICU 4.8 */
|
||||
|
||||
struct UFormattedDateInterval;
|
||||
/**
|
||||
* Opaque struct to contain the results of a UDateIntervalFormat operation.
|
||||
* @stable ICU 64
|
||||
*/
|
||||
typedef struct UFormattedDateInterval UFormattedDateInterval;
|
||||
|
||||
// uversion.h
|
||||
|
||||
/** Maximum length of the copyright string.
|
||||
|
|
|
|||
|
|
@ -140,6 +140,7 @@ namespace RuntimeICUBinder {
|
|||
F(ucal_getType, const char* (*)(const UCalendar* cal, UErrorCode* status), const char*) \
|
||||
F(ucal_getAttribute, int32_t (*)(const UCalendar* cal, UCalendarAttribute attr), int32_t) \
|
||||
F(ucal_getDayOfWeekType, UCalendarWeekdayType (*)(const UCalendar* cal, UCalendarDaysOfWeek dayOfWeek, UErrorCode* status), UCalendarWeekdayType) \
|
||||
F(ucal_clone, UCalendar* (*)(const UCalendar *cal, UErrorCode *status), UCalendar*) \
|
||||
F(udatpg_open, UDateTimePatternGenerator* (*)(const char* locale, UErrorCode* pErrorCode), UDateTimePatternGenerator*) \
|
||||
F(udatpg_getBestPattern, int32_t (*)(UDateTimePatternGenerator * dtpg, const UChar* skeleton, int32_t length, UChar* bestPattern, int32_t capacity, UErrorCode* pErrorCode), int32_t) \
|
||||
F(udatpg_getBestPatternWithOptions, int32_t (*)(UDateTimePatternGenerator*, const UChar*, int32_t, UDateTimePatternMatchOptions, UChar*, int32_t, UErrorCode*), int32_t) \
|
||||
|
|
@ -199,7 +200,10 @@ namespace RuntimeICUBinder {
|
|||
F(ulistfmt_openForType, UListFormatter* (*)(const char* locale, UListFormatterType type, UListFormatterWidth width, UErrorCode* status), UListFormatter*) \
|
||||
F(ulistfmt_format, int32_t (*)(const UListFormatter* listfmt, const UChar* const strings[], const int32_t*, int32_t, UChar*, int32_t, UErrorCode*), int32_t) \
|
||||
F(ulistfmt_openResult, UFormattedList* (*)(UErrorCode * ec), UFormattedList*) \
|
||||
F(ulistfmt_resultAsValue, const UFormattedValue* (*)(const UFormattedList* uresult, UErrorCode* ec), const UFormattedValue*)
|
||||
F(ulistfmt_resultAsValue, const UFormattedValue* (*)(const UFormattedList* uresult, UErrorCode* ec), const UFormattedValue*) \
|
||||
F(udtitvfmt_open, UDateIntervalFormat* (*)(const char*, const UChar*, int32_t, const UChar*, int32_t, UErrorCode*), UDateIntervalFormat*) \
|
||||
F(udtitvfmt_openResult, UFormattedDateInterval* (*)(UErrorCode* ec), UFormattedDateInterval*) \
|
||||
F(udtitvfmt_resultAsValue, const UFormattedValue* (*)(const UFormattedDateInterval*, UErrorCode* ec), const UFormattedValue*)
|
||||
|
||||
#define FOR_EACH_I18N_VOID_OP(F) \
|
||||
F(udat_close, void (*)(UDateFormat * format), void) \
|
||||
|
|
@ -246,7 +250,11 @@ namespace RuntimeICUBinder {
|
|||
F(ucfpos_getIndexes, void (*)(const UConstrainedFieldPosition* ucfpos, int32_t* pStart, int32_t* pLimit, UErrorCode* ec), void) \
|
||||
F(ulistfmt_close, void (*)(UListFormatter * listfmt), void) \
|
||||
F(ulistfmt_formatStringsToResult, void (*)(const UListFormatter*, const UChar* const[], const int32_t*, int32_t, UFormattedList*, UErrorCode*), void) \
|
||||
F(ulistfmt_closeResult, void (*)(UFormattedList * uresult), void)
|
||||
F(ulistfmt_closeResult, void (*)(UFormattedList * uresult), void) \
|
||||
F(udtitvfmt_close, void (*)(UDateIntervalFormat *formatter), void) \
|
||||
F(udtitvfmt_closeResult, void (*)(UFormattedDateInterval* uresult), void) \
|
||||
F(udtitvfmt_formatToResult, void (*)(const UDateIntervalFormat*, UDate, UDate, UFormattedDateInterval*, UErrorCode*), void) \
|
||||
F(udtitvfmt_formatCalendarToResult, void (*)(const UDateIntervalFormat*, UCalendar*, UCalendar*, UFormattedDateInterval*, UErrorCode*), void)
|
||||
|
||||
#define FOR_EACH_I18N_STICKY_OP(F) \
|
||||
F(vzone_getOffset3)
|
||||
|
|
|
|||
|
|
@ -4605,20 +4605,8 @@
|
|||
<test id="intl402/DateTimeFormat/prototype/format/temporal-plaintime-formatting-datetime-style"><reason>TODO</reason></test>
|
||||
<test id="intl402/DateTimeFormat/prototype/format/temporal-plainyearmonth-formatting-datetime-style"><reason>TODO</reason></test>
|
||||
<test id="intl402/DateTimeFormat/prototype/format/temporal-zoneddatetime-not-supported"><reason>TODO</reason></test>
|
||||
<test id="intl402/DateTimeFormat/prototype/formatRange/argument-date-string"><reason>TODO</reason></test>
|
||||
<test id="intl402/DateTimeFormat/prototype/formatRange/argument-near-time-boundaries"><reason>TODO</reason></test>
|
||||
<test id="intl402/DateTimeFormat/prototype/formatRange/argument-to-integer"><reason>TODO</reason></test>
|
||||
<test id="intl402/DateTimeFormat/prototype/formatRange/argument-tonumber-throws"><reason>TODO</reason></test>
|
||||
<test id="intl402/DateTimeFormat/prototype/formatRange/builtin"><reason>TODO</reason></test>
|
||||
<test id="intl402/DateTimeFormat/prototype/formatRange/date-is-infinity-throws"><reason>TODO</reason></test>
|
||||
<test id="intl402/DateTimeFormat/prototype/formatRange/date-is-nan-throws"><reason>TODO</reason></test>
|
||||
<test id="intl402/DateTimeFormat/prototype/formatRange/date-same-returns-single-date"><reason>TODO</reason></test>
|
||||
<test id="intl402/DateTimeFormat/prototype/formatRange/date-x-greater-than-y-not-throws"><reason>TODO</reason></test>
|
||||
<test id="intl402/DateTimeFormat/prototype/formatRange/en-US"><reason>TODO</reason></test>
|
||||
<test id="intl402/DateTimeFormat/prototype/formatRange/fractionalSecondDigits"><reason>TODO</reason></test>
|
||||
<test id="intl402/DateTimeFormat/prototype/formatRange/length"><reason>TODO</reason></test>
|
||||
<test id="intl402/DateTimeFormat/prototype/formatRange/name"><reason>TODO</reason></test>
|
||||
<test id="intl402/DateTimeFormat/prototype/formatRange/prop-desc"><reason>TODO</reason></test>
|
||||
<test id="intl402/DateTimeFormat/prototype/formatRange/temporal-objects-not-overlapping-options"><reason>TODO</reason></test>
|
||||
<test id="intl402/DateTimeFormat/prototype/formatRange/temporal-objects-resolved-time-zone"><reason>TODO</reason></test>
|
||||
<test id="intl402/DateTimeFormat/prototype/formatRange/temporal-zoneddatetime-not-supported"><reason>TODO</reason></test>
|
||||
|
|
@ -4652,8 +4640,6 @@
|
|||
<test id="intl402/DateTimeFormat/prototype/resolvedOptions/offset-timezone-basic"><reason>TODO</reason></test>
|
||||
<test id="intl402/DateTimeFormat/prototype/resolvedOptions/offset-timezone-change"><reason>TODO</reason></test>
|
||||
<test id="intl402/DateTimeFormat/prototype/resolvedOptions/resolved-hour-cycle-unicode-extensions-and-options"><reason>TODO</reason></test>
|
||||
<test id="intl402/DateTimeFormat/prototype/toStringTag/toString"><reason>TODO</reason></test>
|
||||
<test id="intl402/DateTimeFormat/prototype/toStringTag/toStringTag"><reason>TODO</reason></test>
|
||||
<test id="intl402/DateTimeFormat/timezone-case-insensitive"><reason>TODO</reason></test>
|
||||
<test id="intl402/DateTimeFormat/timezone-legacy-non-iana"><reason>TODO</reason></test>
|
||||
<test id="intl402/DateTimeFormat/timezone-not-canonicalized"><reason>TODO</reason></test>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue