EncodedJSValue JSC_HOST_CALL dateProtoFuncToISOString(ExecState* exec) { JSValue thisValue = exec->thisValue(); if (!thisValue.inherits(DateInstance::info())) return throwVMTypeError(exec); DateInstance* thisDateObj = asDateInstance(thisValue); if (!std::isfinite(thisDateObj->internalNumber())) return throwVMError(exec, createRangeError(exec, ASCIILiteral("Invalid Date"))); const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec); if (!gregorianDateTime) return JSValue::encode(jsNontrivialString(exec, String(ASCIILiteral("Invalid Date")))); // Maximum amount of space we need in buffer: 7 (max. digits in year) + 2 * 5 (2 characters each for month, day, hour, minute, second) + 4 (. + 3 digits for milliseconds) // 6 for formatting and one for null termination = 28. We add one extra character to allow us to force null termination. char buffer[28]; // If the year is outside the bounds of 0 and 9999 inclusive we want to use the extended year format (ES 15.9.1.15.1). int ms = static_cast<int>(fmod(thisDateObj->internalNumber(), msPerSecond)); if (ms < 0) ms += msPerSecond; int charactersWritten; if (gregorianDateTime->year() > 9999 || gregorianDateTime->year() < 0) charactersWritten = snprintf(buffer, sizeof(buffer), "%+07d-%02d-%02dT%02d:%02d:%02d.%03dZ", gregorianDateTime->year(), gregorianDateTime->month() + 1, gregorianDateTime->monthDay(), gregorianDateTime->hour(), gregorianDateTime->minute(), gregorianDateTime->second(), ms); else charactersWritten = snprintf(buffer, sizeof(buffer), "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", gregorianDateTime->year(), gregorianDateTime->month() + 1, gregorianDateTime->monthDay(), gregorianDateTime->hour(), gregorianDateTime->minute(), gregorianDateTime->second(), ms); ASSERT(charactersWritten > 0 && static_cast<unsigned>(charactersWritten) < sizeof(buffer)); if (static_cast<unsigned>(charactersWritten) >= sizeof(buffer)) return JSValue::encode(jsEmptyString(exec)); return JSValue::encode(jsNontrivialString(exec, String(buffer, charactersWritten))); }
EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCSeconds(ExecState* exec) { JSValue thisValue = exec->thisValue(); if (!thisValue.inherits(DateInstance::info())) return throwVMTypeError(exec); DateInstance* thisDateObj = asDateInstance(thisValue); const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec); if (!gregorianDateTime) return JSValue::encode(jsNaN()); return JSValue::encode(jsNumber(gregorianDateTime->second())); }
EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCFullYear(ExecState* exec) { JSValue thisValue = exec->hostThisValue(); if (!thisValue.inherits(&DateInstance::s_info)) return throwVMTypeError(exec); DateInstance* thisDateObj = asDateInstance(thisValue); const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec); if (!gregorianDateTime) return JSValue::encode(jsNaN()); return JSValue::encode(jsNumber(1900 + gregorianDateTime->year)); }
static EncodedJSValue formateDateInstance(ExecState* exec, DateTimeFormat format, bool asUTCVariant) { JSValue thisValue = exec->thisValue(); if (!thisValue.inherits(DateInstance::info())) return throwVMTypeError(exec); DateInstance* thisDateObj = asDateInstance(thisValue); const GregorianDateTime* gregorianDateTime = asUTCVariant ? thisDateObj->gregorianDateTimeUTC(exec) : thisDateObj->gregorianDateTime(exec); if (!gregorianDateTime) return JSValue::encode(jsNontrivialString(exec, String(ASCIILiteral("Invalid Date")))); return JSValue::encode(jsNontrivialString(exec, formatDateTime(*gregorianDateTime, format, asUTCVariant))); }
EncodedJSValue JSC_HOST_CALL dateProtoFuncToGMTString(ExecState* exec) { JSValue thisValue = exec->hostThisValue(); if (!thisValue.inherits(&DateInstance::s_info)) return throwVMTypeError(exec); DateInstance* thisDateObj = asDateInstance(thisValue); const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec); if (!gregorianDateTime) return JSValue::encode(jsNontrivialString(exec, "Invalid Date")); DateConversionBuffer date; DateConversionBuffer time; formatDateUTCVariant(*gregorianDateTime, date); formatTimeUTC(*gregorianDateTime, time); return JSValue::encode(jsMakeNontrivialString(exec, date, " ", time)); }
EncodedJSValue JSC_HOST_CALL dateProtoFuncToISOString(ExecState* exec) { JSValue thisValue = exec->hostThisValue(); if (!thisValue.inherits(&DateInstance::s_info)) return throwVMTypeError(exec); DateInstance* thisDateObj = asDateInstance(thisValue); const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec); if (!gregorianDateTime) return JSValue::encode(jsNontrivialString(exec, "Invalid Date")); // Maximum amount of space we need in buffer: 6 (max. digits in year) + 2 * 5 (2 characters each for month, day, hour, minute, second) + 4 (. + 3 digits for milliseconds) // 6 for formatting and one for null termination = 27. We add one extra character to allow us to force null termination. char buffer[28]; snprintf(buffer, sizeof(buffer) - 1, "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", 1900 + gregorianDateTime->year, gregorianDateTime->month + 1, gregorianDateTime->monthDay, gregorianDateTime->hour, gregorianDateTime->minute, gregorianDateTime->second, static_cast<int>(fmod(thisDateObj->internalNumber(), 1000))); buffer[sizeof(buffer) - 1] = 0; return JSValue::encode(jsNontrivialString(exec, buffer)); }
static EncodedJSValue setNewValueFromDateArgs(ExecState* exec, int numArgsToUse, bool inputIsUTC) { JSValue thisValue = exec->thisValue(); if (!thisValue.inherits(DateInstance::info())) return throwVMTypeError(exec); DateInstance* thisDateObj = asDateInstance(thisValue); if (!exec->argumentCount()) { JSValue result = jsNaN(); thisDateObj->setInternalValue(exec->vm(), result); return JSValue::encode(result); } VM& vm = exec->vm(); double milli = thisDateObj->internalNumber(); double ms = 0; GregorianDateTime gregorianDateTime; if (numArgsToUse == 3 && std::isnan(milli)) msToGregorianDateTime(vm, 0, true, gregorianDateTime); else { ms = milli - floor(milli / msPerSecond) * msPerSecond; const GregorianDateTime* other = inputIsUTC ? thisDateObj->gregorianDateTimeUTC(exec) : thisDateObj->gregorianDateTime(exec); if (!other) return JSValue::encode(jsNaN()); gregorianDateTime.copyFrom(*other); } if (!fillStructuresUsingDateArgs(exec, numArgsToUse, &ms, &gregorianDateTime)) { JSValue result = jsNaN(); thisDateObj->setInternalValue(vm, result); return JSValue::encode(result); } JSValue result = jsNumber(gregorianDateTimeToMS(vm, gregorianDateTime, ms, inputIsUTC)); thisDateObj->setInternalValue(vm, result); return JSValue::encode(result); }
static EncodedJSValue setNewValueFromTimeArgs(ExecState* exec, int numArgsToUse, bool inputIsUTC) { JSValue thisValue = exec->hostThisValue(); if (!thisValue.inherits(&DateInstance::s_info)) return throwVMTypeError(exec); DateInstance* thisDateObj = asDateInstance(thisValue); double milli = thisDateObj->internalNumber(); if (!exec->argumentCount() || isnan(milli)) { JSValue result = jsNaN(); thisDateObj->setInternalValue(exec->globalData(), result); return JSValue::encode(result); } double secs = floor(milli / msPerSecond); double ms = milli - secs * msPerSecond; const GregorianDateTime* other = inputIsUTC ? thisDateObj->gregorianDateTimeUTC(exec) : thisDateObj->gregorianDateTime(exec); if (!other) return JSValue::encode(jsNaN()); GregorianDateTime gregorianDateTime; gregorianDateTime.copyFrom(*other); if (!fillStructuresUsingTimeArgs(exec, numArgsToUse, &ms, &gregorianDateTime)) { JSValue result = jsNaN(); thisDateObj->setInternalValue(exec->globalData(), result); return JSValue::encode(result); } JSValue result = jsNumber(gregorianDateTimeToMS(exec, gregorianDateTime, ms, inputIsUTC)); thisDateObj->setInternalValue(exec->globalData(), result); return JSValue::encode(result); }
EncodedJSValue JSC_HOST_CALL dateProtoFuncToISOString(ExecState* exec) { JSValue thisValue = exec->hostThisValue(); if (!thisValue.inherits(&DateInstance::s_info)) return throwVMTypeError(exec); DateInstance* thisDateObj = asDateInstance(thisValue); if (!isfinite(thisDateObj->internalNumber())) return throwVMError(exec, createRangeError(exec, "Invalid Date")); const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec); if (!gregorianDateTime) return JSValue::encode(jsNontrivialString(exec, "Invalid Date")); // Maximum amount of space we need in buffer: 7 (max. digits in year) + 2 * 5 (2 characters each for month, day, hour, minute, second) + 4 (. + 3 digits for milliseconds) // 6 for formatting and one for null termination = 28. We add one extra character to allow us to force null termination. char buffer[29]; // If the year is outside the bounds of 0 and 9999 inclusive we want to use the extended year format (ES 15.9.1.15.1). if (gregorianDateTime->year > 8099 || gregorianDateTime->year < -1900) snprintf(buffer, sizeof(buffer) - 1, "%+07d-%02d-%02dT%02d:%02d:%02d.%03dZ", 1900 + gregorianDateTime->year, gregorianDateTime->month + 1, gregorianDateTime->monthDay, gregorianDateTime->hour, gregorianDateTime->minute, gregorianDateTime->second, static_cast<int>(fmod(thisDateObj->internalNumber(), 1000))); else snprintf(buffer, sizeof(buffer) - 1, "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", 1900 + gregorianDateTime->year, gregorianDateTime->month + 1, gregorianDateTime->monthDay, gregorianDateTime->hour, gregorianDateTime->minute, gregorianDateTime->second, static_cast<int>(fmod(thisDateObj->internalNumber(), 1000))); buffer[sizeof(buffer) - 1] = 0; return JSValue::encode(jsNontrivialString(exec, buffer)); }