2 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
23 #include "date_object.h"
24 #include "date_object.lut.h"
32 #include <sys/param.h>
40 #include <sys/timeb.h>
52 #include "error_object.h"
53 #include "operations.h"
56 #include <wtf/ASCIICType.h>
57 #include <wtf/Assertions.h>
58 #include <wtf/MathExtras.h>
59 #include <wtf/StringExtras.h>
60 #include <wtf/UnusedParam.h>
63 #include <CoreFoundation/CoreFoundation.h>
70 static double parseDate(const UString&);
71 static double timeClip(double);
73 inline int gmtoffset(const GregorianDateTime& t)
82 * Class to implement all methods that are properties of the
85 class DateObjectFuncImp : public InternalFunctionImp {
87 DateObjectFuncImp(ExecState *, FunctionPrototype *, int i, int len, const Identifier& );
89 virtual JSValue *callAsFunction(ExecState *, JSObject *thisObj, const List &args);
97 struct DateInstance::Cache {
98 double m_gregorianDateTimeCachedForMS;
99 GregorianDateTime m_cachedGregorianDateTime;
100 double m_gregorianDateTimeUTCCachedForMS;
101 GregorianDateTime m_cachedGregorianDateTimeUTC;
106 static CFDateFormatterStyle styleFromArgString(const UString& string, CFDateFormatterStyle defaultStyle)
108 if (string == "short")
109 return kCFDateFormatterShortStyle;
110 if (string == "medium")
111 return kCFDateFormatterMediumStyle;
112 if (string == "long")
113 return kCFDateFormatterLongStyle;
114 if (string == "full")
115 return kCFDateFormatterFullStyle;
119 static UString formatLocaleDate(ExecState *exec, double time, bool includeDate, bool includeTime, const List &args)
121 CFDateFormatterStyle dateStyle = (includeDate ? kCFDateFormatterLongStyle : kCFDateFormatterNoStyle);
122 CFDateFormatterStyle timeStyle = (includeTime ? kCFDateFormatterLongStyle : kCFDateFormatterNoStyle);
124 bool useCustomFormat = false;
125 UString customFormatString;
127 UString arg0String = args[0]->toString(exec);
128 if (arg0String == "custom" && !args[1]->isUndefined()) {
129 useCustomFormat = true;
130 customFormatString = args[1]->toString(exec);
131 } else if (includeDate && includeTime && !args[1]->isUndefined()) {
132 dateStyle = styleFromArgString(arg0String, dateStyle);
133 timeStyle = styleFromArgString(args[1]->toString(exec), timeStyle);
134 } else if (includeDate && !args[0]->isUndefined()) {
135 dateStyle = styleFromArgString(arg0String, dateStyle);
136 } else if (includeTime && !args[0]->isUndefined()) {
137 timeStyle = styleFromArgString(arg0String, timeStyle);
140 CFLocaleRef locale = CFLocaleCopyCurrent();
141 CFDateFormatterRef formatter = CFDateFormatterCreate(0, locale, dateStyle, timeStyle);
144 if (useCustomFormat) {
145 CFStringRef customFormatCFString = CFStringCreateWithCharacters(0, (UniChar *)customFormatString.data(), customFormatString.size());
146 CFDateFormatterSetFormat(formatter, customFormatCFString);
147 CFRelease(customFormatCFString);
150 CFStringRef string = CFDateFormatterCreateStringWithAbsoluteTime(0, formatter, time - kCFAbsoluteTimeIntervalSince1970);
152 CFRelease(formatter);
154 // We truncate the string returned from CFDateFormatter if it's absurdly long (> 200 characters).
155 // That's not great error handling, but it just won't happen so it doesn't matter.
157 const size_t bufferLength = sizeof(buffer) / sizeof(buffer[0]);
158 size_t length = CFStringGetLength(string);
159 ASSERT(length <= bufferLength);
160 if (length > bufferLength)
161 length = bufferLength;
162 CFStringGetCharacters(string, CFRangeMake(0, length), reinterpret_cast<UniChar *>(buffer));
166 return UString(buffer, length);
171 enum LocaleDateTimeFormat { LocaleDateAndTime, LocaleDate, LocaleTime };
173 static JSCell* formatLocaleDate(const GregorianDateTime& gdt, const LocaleDateTimeFormat format)
175 static const char* formatStrings[] = {"%#c", "%#x", "%X"};
177 // Offset year if needed
178 struct tm localTM = gdt;
179 int year = gdt.year + 1900;
180 bool yearNeedsOffset = year < 1900 || year > 2038;
181 if (yearNeedsOffset) {
182 localTM.tm_year = equivalentYearForDST(year) - 1900;
186 const int bufsize=128;
187 char timebuffer[bufsize];
188 size_t ret = strftime(timebuffer, bufsize, formatStrings[format], &localTM);
193 // Copy original into the buffer
194 if (yearNeedsOffset && format != LocaleTime) {
195 static const int yearLen = 5; // FIXME will be a problem in the year 10,000
196 char yearString[yearLen];
198 snprintf(yearString, yearLen, "%d", localTM.tm_year + 1900);
199 char* yearLocation = strstr(timebuffer, yearString);
200 snprintf(yearString, yearLen, "%d", year);
202 strncpy(yearLocation, yearString, yearLen - 1);
205 return jsString(timebuffer);
208 #endif // PLATFORM(WIN_OS)
210 static UString formatDate(const GregorianDateTime &t)
213 snprintf(buffer, sizeof(buffer), "%s %s %02d %04d",
214 weekdayName[(t.weekDay + 6) % 7],
215 monthName[t.month], t.monthDay, t.year + 1900);
219 static UString formatDateUTCVariant(const GregorianDateTime &t)
222 snprintf(buffer, sizeof(buffer), "%s, %02d %s %04d",
223 weekdayName[(t.weekDay + 6) % 7],
224 t.monthDay, monthName[t.month], t.year + 1900);
228 static UString formatTime(const GregorianDateTime &t, bool utc)
232 snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d GMT", t.hour, t.minute, t.second);
234 int offset = abs(gmtoffset(t));
237 strftime(tzname, sizeof(tzname), "%Z", >m);
240 snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d GMT%c%02d%02d (%s)",
241 t.hour, t.minute, t.second,
242 gmtoffset(t) < 0 ? '-' : '+', offset / (60*60), (offset / 60) % 60, tzname);
244 snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d GMT%c%02d%02d",
245 t.hour, t.minute, t.second,
246 gmtoffset(t) < 0 ? '-' : '+', offset / (60*60), (offset / 60) % 60);
249 return UString(buffer);
252 // Converts a list of arguments sent to a Date member function into milliseconds, updating
253 // ms (representing milliseconds) and t (representing the rest of the date structure) appropriately.
255 // Format of member function: f([hour,] [min,] [sec,] [ms])
256 static bool fillStructuresUsingTimeArgs(ExecState* exec, const List& args, int maxArgs, double* ms, GregorianDateTime* t)
258 double milliseconds = 0;
261 int numArgs = args.size();
263 // JS allows extra trailing arguments -- ignore them
264 if (numArgs > maxArgs)
268 if (maxArgs >= 4 && idx < numArgs) {
270 milliseconds += args[idx++]->toInt32(exec, ok) * msPerHour;
274 if (maxArgs >= 3 && idx < numArgs && ok) {
276 milliseconds += args[idx++]->toInt32(exec, ok) * msPerMinute;
280 if (maxArgs >= 2 && idx < numArgs && ok) {
282 milliseconds += args[idx++]->toInt32(exec, ok) * msPerSecond;
290 double millis = args[idx]->toNumber(exec);
291 ok = isfinite(millis);
292 milliseconds += millis;
300 // Converts a list of arguments sent to a Date member function into years, months, and milliseconds, updating
301 // ms (representing milliseconds) and t (representing the rest of the date structure) appropriately.
303 // Format of member function: f([years,] [months,] [days])
304 static bool fillStructuresUsingDateArgs(ExecState *exec, const List &args, int maxArgs, double *ms, GregorianDateTime *t)
308 int numArgs = args.size();
310 // JS allows extra trailing arguments -- ignore them
311 if (numArgs > maxArgs)
315 if (maxArgs >= 3 && idx < numArgs)
316 t->year = args[idx++]->toInt32(exec, ok) - 1900;
319 if (maxArgs >= 2 && idx < numArgs && ok)
320 t->month = args[idx++]->toInt32(exec, ok);
323 if (idx < numArgs && ok) {
325 *ms += args[idx]->toInt32(exec, ok) * msPerDay;
331 // ------------------------------ DateInstance ------------------------------
333 const ClassInfo DateInstance::info = {"Date", 0, 0, 0};
335 DateInstance::DateInstance(JSObject *proto)
336 : JSWrapperObject(proto)
341 DateInstance::~DateInstance()
346 void DateInstance::msToGregorianDateTime(double milli, bool outputIsUTC, GregorianDateTime& t) const
350 m_cache->m_gregorianDateTimeCachedForMS = NaN;
351 m_cache->m_gregorianDateTimeUTCCachedForMS = NaN;
355 if (m_cache->m_gregorianDateTimeUTCCachedForMS != milli) {
356 KJS::msToGregorianDateTime(milli, true, m_cache->m_cachedGregorianDateTimeUTC);
357 m_cache->m_gregorianDateTimeUTCCachedForMS = milli;
359 t.copyFrom(m_cache->m_cachedGregorianDateTimeUTC);
361 if (m_cache->m_gregorianDateTimeCachedForMS != milli) {
362 KJS::msToGregorianDateTime(milli, false, m_cache->m_cachedGregorianDateTime);
363 m_cache->m_gregorianDateTimeCachedForMS = milli;
365 t.copyFrom(m_cache->m_cachedGregorianDateTime);
369 bool DateInstance::getTime(GregorianDateTime &t, int &offset) const
371 double milli = internalValue()->getNumber();
375 msToGregorianDateTime(milli, false, t);
376 offset = gmtoffset(t);
380 bool DateInstance::getUTCTime(GregorianDateTime &t) const
382 double milli = internalValue()->getNumber();
386 msToGregorianDateTime(milli, true, t);
390 bool DateInstance::getTime(double &milli, int &offset) const
392 milli = internalValue()->getNumber();
397 msToGregorianDateTime(milli, false, t);
398 offset = gmtoffset(t);
402 bool DateInstance::getUTCTime(double &milli) const
404 milli = internalValue()->getNumber();
411 static inline bool isTime_tSigned()
413 time_t minusOne = (time_t)(-1);
417 // ------------------------------ DatePrototype -----------------------------
419 const ClassInfo DatePrototype::info = {"Date", &DateInstance::info, 0, ExecState::dateTable};
421 /* Source for date_object.lut.h
422 FIXMEL We could use templates to simplify the UTC variants.
424 toString dateProtoFuncToString DontEnum|Function 0
425 toUTCString dateProtoFuncToUTCString DontEnum|Function 0
426 toDateString dateProtoFuncToDateString DontEnum|Function 0
427 toTimeString dateProtoFuncToTimeString DontEnum|Function 0
428 toLocaleString dateProtoFuncToLocaleString DontEnum|Function 0
429 toLocaleDateString dateProtoFuncToLocaleDateString DontEnum|Function 0
430 toLocaleTimeString dateProtoFuncToLocaleTimeString DontEnum|Function 0
431 valueOf dateProtoFuncValueOf DontEnum|Function 0
432 getTime dateProtoFuncGetTime DontEnum|Function 0
433 getFullYear dateProtoFuncGetFullYear DontEnum|Function 0
434 getUTCFullYear dateProtoFuncGetUTCFullYear DontEnum|Function 0
435 toGMTString dateProtoFuncToGMTString DontEnum|Function 0
436 getMonth dateProtoFuncGetMonth DontEnum|Function 0
437 getUTCMonth dateProtoFuncGetUTCMonth DontEnum|Function 0
438 getDate dateProtoFuncGetDate DontEnum|Function 0
439 getUTCDate dateProtoFuncGetUTCDate DontEnum|Function 0
440 getDay dateProtoFuncGetDay DontEnum|Function 0
441 getUTCDay dateProtoFuncGetUTCDay DontEnum|Function 0
442 getHours dateProtoFuncGetHours DontEnum|Function 0
443 getUTCHours dateProtoFuncGetUTCHours DontEnum|Function 0
444 getMinutes dateProtoFuncGetMinutes DontEnum|Function 0
445 getUTCMinutes dateProtoFuncGetUTCMinutes DontEnum|Function 0
446 getSeconds dateProtoFuncGetSeconds DontEnum|Function 0
447 getUTCSeconds dateProtoFuncGetUTCSeconds DontEnum|Function 0
448 getMilliseconds dateProtoFuncGetMilliSeconds DontEnum|Function 0
449 getUTCMilliseconds dateProtoFuncGetUTCMilliseconds DontEnum|Function 0
450 getTimezoneOffset dateProtoFuncGetTimezoneOffset DontEnum|Function 0
451 setTime dateProtoFuncSetTime DontEnum|Function 1
452 setMilliseconds dateProtoFuncSetMilliSeconds DontEnum|Function 1
453 setUTCMilliseconds dateProtoFuncSetUTCMilliseconds DontEnum|Function 1
454 setSeconds dateProtoFuncSetSeconds DontEnum|Function 2
455 setUTCSeconds dateProtoFuncSetUTCSeconds DontEnum|Function 2
456 setMinutes dateProtoFuncSetMinutes DontEnum|Function 3
457 setUTCMinutes dateProtoFuncSetUTCMinutes DontEnum|Function 3
458 setHours dateProtoFuncSetHours DontEnum|Function 4
459 setUTCHours dateProtoFuncSetUTCHours DontEnum|Function 4
460 setDate dateProtoFuncSetDate DontEnum|Function 1
461 setUTCDate dateProtoFuncSetUTCDate DontEnum|Function 1
462 setMonth dateProtoFuncSetMonth DontEnum|Function 2
463 setUTCMonth dateProtoFuncSetUTCMonth DontEnum|Function 2
464 setFullYear dateProtoFuncSetFullYear DontEnum|Function 3
465 setUTCFullYear dateProtoFuncSetUTCFullYear DontEnum|Function 3
466 setYear dateProtoFuncSetYear DontEnum|Function 1
467 getYear dateProtoFuncGetYear DontEnum|Function 0
472 DatePrototype::DatePrototype(ExecState *, ObjectPrototype *objectProto)
473 : DateInstance(objectProto)
475 setInternalValue(jsNaN());
476 // The constructor will be added later, after DateObjectImp has been built.
479 bool DatePrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
481 return getStaticFunctionSlot<JSObject>(exec, ExecState::dateTable(exec), this, propertyName, slot);
484 // ------------------------------ DateObjectImp --------------------------------
486 // TODO: MakeTime (15.9.11.1) etc. ?
488 DateObjectImp::DateObjectImp(ExecState* exec, FunctionPrototype* funcProto, DatePrototype* dateProto)
489 : InternalFunctionImp(funcProto, dateProto->classInfo()->className)
491 putDirect(exec->propertyNames().prototype, dateProto, DontEnum|DontDelete|ReadOnly);
492 putDirectFunction(new DateObjectFuncImp(exec, funcProto, DateObjectFuncImp::Parse, 1, exec->propertyNames().parse), DontEnum);
493 putDirectFunction(new DateObjectFuncImp(exec, funcProto, DateObjectFuncImp::UTC, 7, exec->propertyNames().UTC), DontEnum);
494 putDirect(exec->propertyNames().length, 7, ReadOnly|DontDelete|DontEnum);
497 bool DateObjectImp::implementsConstruct() const
503 JSObject *DateObjectImp::construct(ExecState *exec, const List &args)
505 int numArgs = args.size();
509 if (numArgs == 0) { // new Date() ECMA 15.9.3.3
510 value = getCurrentUTCTime();
511 } else if (numArgs == 1) {
512 if (args[0]->isObject(&DateInstance::info))
513 value = static_cast<DateInstance*>(args[0])->internalValue()->toNumber(exec);
515 JSValue* primitive = args[0]->toPrimitive(exec);
516 if (primitive->isString())
517 value = parseDate(primitive->getString());
519 value = primitive->toNumber(exec);
522 if (isnan(args[0]->toNumber(exec))
523 || isnan(args[1]->toNumber(exec))
524 || (numArgs >= 3 && isnan(args[2]->toNumber(exec)))
525 || (numArgs >= 4 && isnan(args[3]->toNumber(exec)))
526 || (numArgs >= 5 && isnan(args[4]->toNumber(exec)))
527 || (numArgs >= 6 && isnan(args[5]->toNumber(exec)))
528 || (numArgs >= 7 && isnan(args[6]->toNumber(exec)))) {
532 int year = args[0]->toInt32(exec);
533 t.year = (year >= 0 && year <= 99) ? year : year - 1900;
534 t.month = args[1]->toInt32(exec);
535 t.monthDay = (numArgs >= 3) ? args[2]->toInt32(exec) : 1;
536 t.hour = args[3]->toInt32(exec);
537 t.minute = args[4]->toInt32(exec);
538 t.second = args[5]->toInt32(exec);
540 double ms = (numArgs >= 7) ? args[6]->toNumber(exec) : 0;
541 value = gregorianDateTimeToMS(t, ms, false);
545 DateInstance *ret = new DateInstance(exec->lexicalGlobalObject()->datePrototype());
546 ret->setInternalValue(jsNumber(timeClip(value)));
551 JSValue *DateObjectImp::callAsFunction(ExecState * /*exec*/, JSObject * /*thisObj*/, const List &/*args*/)
553 time_t localTime = time(0);
555 getLocalTime(&localTime, &localTM);
556 GregorianDateTime ts(localTM);
557 return jsString(formatDate(ts) + " " + formatTime(ts, false));
560 // ------------------------------ DateObjectFuncImp ----------------------------
562 DateObjectFuncImp::DateObjectFuncImp(ExecState* exec, FunctionPrototype* funcProto, int i, int len, const Identifier& name)
563 : InternalFunctionImp(funcProto, name), id(i)
565 putDirect(exec->propertyNames().length, len, DontDelete|ReadOnly|DontEnum);
569 JSValue *DateObjectFuncImp::callAsFunction(ExecState* exec, JSObject*, const List& args)
572 return jsNumber(parseDate(args[0]->toString(exec)));
576 if (isnan(args[0]->toNumber(exec))
577 || isnan(args[1]->toNumber(exec))
578 || (n >= 3 && isnan(args[2]->toNumber(exec)))
579 || (n >= 4 && isnan(args[3]->toNumber(exec)))
580 || (n >= 5 && isnan(args[4]->toNumber(exec)))
581 || (n >= 6 && isnan(args[5]->toNumber(exec)))
582 || (n >= 7 && isnan(args[6]->toNumber(exec)))) {
587 int year = args[0]->toInt32(exec);
588 t.year = (year >= 0 && year <= 99) ? year : year - 1900;
589 t.month = args[1]->toInt32(exec);
590 t.monthDay = (n >= 3) ? args[2]->toInt32(exec) : 1;
591 t.hour = args[3]->toInt32(exec);
592 t.minute = args[4]->toInt32(exec);
593 t.second = args[5]->toInt32(exec);
594 double ms = (n >= 7) ? args[6]->toNumber(exec) : 0;
595 return jsNumber(gregorianDateTimeToMS(t, ms, true));
599 // -----------------------------------------------------------------------------
601 // Code originally from krfcdate.cpp, but we don't want to use kdecore, and we want double range.
603 static inline double ymdhmsToSeconds(long year, int mon, int day, int hour, int minute, int second)
605 double days = (day - 32075)
606 + floor(1461 * (year + 4800.0 + (mon - 14) / 12) / 4)
607 + 367 * (mon - 2 - (mon - 14) / 12 * 12) / 12
608 - floor(3 * ((year + 4900.0 + (mon - 14) / 12) / 100) / 4)
610 return ((days * hoursPerDay + hour) * minutesPerHour + minute) * secondsPerMinute + second;
613 // We follow the recommendation of RFC 2822 to consider all
614 // obsolete time zones not listed here equivalent to "-0000".
615 static const struct KnownZone {
616 #if !PLATFORM(WIN_OS)
634 inline static void skipSpacesAndComments(const char*& s)
639 if (!isASCIISpace(ch)) {
642 else if (ch == ')' && nesting > 0)
644 else if (nesting == 0)
651 // returns 0-11 (Jan-Dec); -1 on failure
652 static int findMonth(const char* monthStr)
656 for (int i = 0; i < 3; ++i) {
659 needle[i] = static_cast<char>(toASCIILower(*monthStr++));
662 const char *haystack = "janfebmaraprmayjunjulaugsepoctnovdec";
663 const char *str = strstr(haystack, needle);
665 int position = static_cast<int>(str - haystack);
666 if (position % 3 == 0)
672 static double parseDate(const UString &date)
674 // This parses a date in the form:
675 // Tuesday, 09-Nov-99 23:12:40 GMT
677 // Sat, 01-Jan-2000 08:00:00 GMT
679 // Sat, 01 Jan 2000 08:00:00 GMT
681 // 01 Jan 99 22:00 +0100 (exceptions in rfc822/rfc2822)
682 // ### non RFC formats, added for Javascript:
683 // [Wednesday] January 09 1999 23:12:40 GMT
684 // [Wednesday] January 09 23:12:40 GMT 1999
686 // We ignore the weekday.
688 CString dateCString = date.UTF8String();
689 const char *dateString = dateCString.c_str();
691 // Skip leading space
692 skipSpacesAndComments(dateString);
695 const char *wordStart = dateString;
696 // Check contents of first words if not number
697 while (*dateString && !isASCIIDigit(*dateString)) {
698 if (isASCIISpace(*dateString) || *dateString == '(') {
699 if (dateString - wordStart >= 3)
700 month = findMonth(wordStart);
701 skipSpacesAndComments(dateString);
702 wordStart = dateString;
707 // Missing delimiter between month and day (like "January29")?
708 if (month == -1 && wordStart != dateString)
709 month = findMonth(wordStart);
711 skipSpacesAndComments(dateString);
716 // ' 09-Nov-99 23:12:40 GMT'
719 long day = strtol(dateString, &newPosStr, 10);
722 dateString = newPosStr;
732 // ### where is the boundary and what happens below?
733 if (*dateString != '/')
735 // looks like a YYYY/MM/DD date
739 month = strtol(dateString, &newPosStr, 10) - 1;
742 dateString = newPosStr;
743 if (*dateString++ != '/' || !*dateString)
745 day = strtol(dateString, &newPosStr, 10);
748 dateString = newPosStr;
749 } else if (*dateString == '/' && month == -1) {
751 // This looks like a MM/DD/YYYY date, not an RFC date.
752 month = day - 1; // 0-based
753 day = strtol(dateString, &newPosStr, 10);
756 if (day < 1 || day > 31)
758 dateString = newPosStr;
759 if (*dateString == '/')
764 if (*dateString == '-')
767 skipSpacesAndComments(dateString);
769 if (*dateString == ',')
772 if (month == -1) { // not found yet
773 month = findMonth(dateString);
777 while (*dateString && *dateString != '-' && *dateString != ',' && !isASCIISpace(*dateString))
783 // '-99 23:12:40 GMT'
784 if (*dateString != '-' && *dateString != '/' && *dateString != ',' && !isASCIISpace(*dateString))
790 if (month < 0 || month > 11)
794 if (year <= 0 && *dateString) {
795 year = strtol(dateString, &newPosStr, 10);
800 // Don't fail if the time is missing.
805 dateString = newPosStr;
808 if (!(isASCIISpace(*newPosStr) || *newPosStr == ',')) {
809 if (*newPosStr != ':')
811 // There was no year; the number was the hour.
814 // in the normal case (we parsed the year), advance to the next number
815 dateString = ++newPosStr;
816 skipSpacesAndComments(dateString);
819 hour = strtol(dateString, &newPosStr, 10);
820 // Do not check for errno here since we want to continue
821 // even if errno was set becasue we are still looking
824 // Read a number? If not, this might be a timezone name.
825 if (newPosStr != dateString) {
826 dateString = newPosStr;
828 if (hour < 0 || hour > 23)
835 if (*dateString++ != ':')
838 minute = strtol(dateString, &newPosStr, 10);
841 dateString = newPosStr;
843 if (minute < 0 || minute > 59)
847 if (*dateString && *dateString != ':' && !isASCIISpace(*dateString))
850 // seconds are optional in rfc822 + rfc2822
851 if (*dateString ==':') {
854 second = strtol(dateString, &newPosStr, 10);
857 dateString = newPosStr;
859 if (second < 0 || second > 59)
863 skipSpacesAndComments(dateString);
865 if (strncasecmp(dateString, "AM", 2) == 0) {
871 skipSpacesAndComments(dateString);
872 } else if (strncasecmp(dateString, "PM", 2) == 0) {
878 skipSpacesAndComments(dateString);
886 // Don't fail if the time zone is missing.
887 // Some websites omit the time zone (4275206).
889 if (strncasecmp(dateString, "GMT", 3) == 0 || strncasecmp(dateString, "UTC", 3) == 0) {
894 if (*dateString == '+' || *dateString == '-') {
895 long o = strtol(dateString, &newPosStr, 10);
898 dateString = newPosStr;
900 if (o < -9959 || o > 9959)
903 int sgn = (o < 0) ? -1 : 1;
905 if (*dateString != ':') {
906 offset = ((o / 100) * 60 + (o % 100)) * sgn;
907 } else { // GMT+05:00
908 long o2 = strtol(dateString, &newPosStr, 10);
911 dateString = newPosStr;
912 offset = (o * 60 + o2) * sgn;
916 for (int i = 0; i < int(sizeof(known_zones) / sizeof(KnownZone)); i++) {
917 if (0 == strncasecmp(dateString, known_zones[i].tzName, strlen(known_zones[i].tzName))) {
918 offset = known_zones[i].tzOffset;
919 dateString += strlen(known_zones[i].tzName);
927 skipSpacesAndComments(dateString);
929 if (*dateString && year == -1) {
930 year = strtol(dateString, &newPosStr, 10);
933 dateString = newPosStr;
936 skipSpacesAndComments(dateString);
942 // Y2K: Handle 2 digit years.
943 if (year >= 0 && year < 100) {
950 // fall back to local timezone
955 t.year = year - 1900;
961 // Use our gregorianDateTimeToMS() rather than mktime() as the latter can't handle the full year range.
962 return gregorianDateTimeToMS(t, 0, false);
965 return (ymdhmsToSeconds(year, month + 1, day, hour, minute, second) - (offset * 60.0)) * msPerSecond;
968 double timeClip(double t)
972 if (fabs(t) > 8.64E15)
979 JSValue* dateProtoFuncToString(ExecState* exec, JSObject* thisObj, const List&)
981 if (!thisObj->inherits(&DateInstance::info))
982 return throwError(exec, TypeError);
984 const bool utc = false;
986 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
987 JSValue* v = thisDateObj->internalValue();
988 double milli = v->toNumber(exec);
990 return jsString("Invalid Date");
993 thisDateObj->msToGregorianDateTime(milli, utc, t);
994 return jsString(formatDate(t) + " " + formatTime(t, utc));
997 JSValue* dateProtoFuncToUTCString(ExecState* exec, JSObject* thisObj, const List&)
999 if (!thisObj->inherits(&DateInstance::info))
1000 return throwError(exec, TypeError);
1002 const bool utc = true;
1004 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1005 JSValue* v = thisDateObj->internalValue();
1006 double milli = v->toNumber(exec);
1008 return jsString("Invalid Date");
1010 GregorianDateTime t;
1011 thisDateObj->msToGregorianDateTime(milli, utc, t);
1012 return jsString(formatDateUTCVariant(t) + " " + formatTime(t, utc));
1015 JSValue* dateProtoFuncToDateString(ExecState* exec, JSObject* thisObj, const List&)
1017 if (!thisObj->inherits(&DateInstance::info))
1018 return throwError(exec, TypeError);
1020 const bool utc = false;
1022 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1023 JSValue* v = thisDateObj->internalValue();
1024 double milli = v->toNumber(exec);
1026 return jsString("Invalid Date");
1028 GregorianDateTime t;
1029 thisDateObj->msToGregorianDateTime(milli, utc, t);
1030 return jsString(formatDate(t));
1033 JSValue* dateProtoFuncToTimeString(ExecState* exec, JSObject* thisObj, const List&)
1035 if (!thisObj->inherits(&DateInstance::info))
1036 return throwError(exec, TypeError);
1038 const bool utc = false;
1040 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1041 JSValue* v = thisDateObj->internalValue();
1042 double milli = v->toNumber(exec);
1044 return jsString("Invalid Date");
1046 GregorianDateTime t;
1047 thisDateObj->msToGregorianDateTime(milli, utc, t);
1048 return jsString(formatTime(t, utc));
1051 JSValue* dateProtoFuncToLocaleString(ExecState* exec, JSObject* thisObj, const List& args)
1053 if (!thisObj->inherits(&DateInstance::info))
1054 return throwError(exec, TypeError);
1056 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1057 JSValue* v = thisDateObj->internalValue();
1058 double milli = v->toNumber(exec);
1060 return jsString("Invalid Date");
1063 double secs = floor(milli / msPerSecond);
1064 return jsString(formatLocaleDate(exec, secs, true, true, args));
1068 const bool utc = false;
1070 GregorianDateTime t;
1071 thisDateObj->msToGregorianDateTime(milli, utc, t);
1072 return formatLocaleDate(t, LocaleDateAndTime);
1076 JSValue* dateProtoFuncToLocaleDateString(ExecState* exec, JSObject* thisObj, const List& args)
1078 if (!thisObj->inherits(&DateInstance::info))
1079 return throwError(exec, TypeError);
1081 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1082 JSValue* v = thisDateObj->internalValue();
1083 double milli = v->toNumber(exec);
1085 return jsString("Invalid Date");
1088 double secs = floor(milli / msPerSecond);
1089 return jsString(formatLocaleDate(exec, secs, true, false, args));
1093 const bool utc = false;
1095 GregorianDateTime t;
1096 thisDateObj->msToGregorianDateTime(milli, utc, t);
1097 return formatLocaleDate(t, LocaleDate);
1101 JSValue* dateProtoFuncToLocaleTimeString(ExecState* exec, JSObject* thisObj, const List& args)
1103 if (!thisObj->inherits(&DateInstance::info))
1104 return throwError(exec, TypeError);
1106 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1107 JSValue* v = thisDateObj->internalValue();
1108 double milli = v->toNumber(exec);
1110 return jsString("Invalid Date");
1113 double secs = floor(milli / msPerSecond);
1114 return jsString(formatLocaleDate(exec, secs, false, true, args));
1118 const bool utc = false;
1120 GregorianDateTime t;
1121 thisDateObj->msToGregorianDateTime(milli, utc, t);
1122 return formatLocaleDate(t, LocaleTime);
1126 JSValue* dateProtoFuncValueOf(ExecState* exec, JSObject* thisObj, const List&)
1128 if (!thisObj->inherits(&DateInstance::info))
1129 return throwError(exec, TypeError);
1131 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1132 JSValue* v = thisDateObj->internalValue();
1133 double milli = v->toNumber(exec);
1137 return jsNumber(milli);
1140 JSValue* dateProtoFuncGetTime(ExecState* exec, JSObject* thisObj, const List&)
1142 if (!thisObj->inherits(&DateInstance::info))
1143 return throwError(exec, TypeError);
1145 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1146 JSValue* v = thisDateObj->internalValue();
1147 double milli = v->toNumber(exec);
1151 return jsNumber(milli);
1154 JSValue* dateProtoFuncGetFullYear(ExecState* exec, JSObject* thisObj, const List&)
1156 if (!thisObj->inherits(&DateInstance::info))
1157 return throwError(exec, TypeError);
1159 const bool utc = false;
1161 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1162 JSValue* v = thisDateObj->internalValue();
1163 double milli = v->toNumber(exec);
1167 GregorianDateTime t;
1168 thisDateObj->msToGregorianDateTime(milli, utc, t);
1169 return jsNumber(1900 + t.year);
1172 JSValue* dateProtoFuncGetUTCFullYear(ExecState* exec, JSObject* thisObj, const List&)
1174 if (!thisObj->inherits(&DateInstance::info))
1175 return throwError(exec, TypeError);
1177 const bool utc = true;
1179 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1180 JSValue* v = thisDateObj->internalValue();
1181 double milli = v->toNumber(exec);
1185 GregorianDateTime t;
1186 thisDateObj->msToGregorianDateTime(milli, utc, t);
1187 return jsNumber(1900 + t.year);
1190 JSValue* dateProtoFuncToGMTString(ExecState* exec, JSObject* thisObj, const List&)
1192 if (!thisObj->inherits(&DateInstance::info))
1193 return throwError(exec, TypeError);
1195 const bool utc = true;
1197 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1198 JSValue* v = thisDateObj->internalValue();
1199 double milli = v->toNumber(exec);
1201 return jsString("Invalid Date");
1203 GregorianDateTime t;
1204 thisDateObj->msToGregorianDateTime(milli, utc, t);
1205 return jsString(formatDateUTCVariant(t) + " " + formatTime(t, utc));
1208 JSValue* dateProtoFuncGetMonth(ExecState* exec, JSObject* thisObj, const List&)
1210 if (!thisObj->inherits(&DateInstance::info))
1211 return throwError(exec, TypeError);
1213 const bool utc = false;
1215 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1216 JSValue* v = thisDateObj->internalValue();
1217 double milli = v->toNumber(exec);
1221 GregorianDateTime t;
1222 thisDateObj->msToGregorianDateTime(milli, utc, t);
1223 return jsNumber(t.month);
1226 JSValue* dateProtoFuncGetUTCMonth(ExecState* exec, JSObject* thisObj, const List&)
1228 if (!thisObj->inherits(&DateInstance::info))
1229 return throwError(exec, TypeError);
1231 const bool utc = true;
1233 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1234 JSValue* v = thisDateObj->internalValue();
1235 double milli = v->toNumber(exec);
1239 GregorianDateTime t;
1240 thisDateObj->msToGregorianDateTime(milli, utc, t);
1241 return jsNumber(t.month);
1244 JSValue* dateProtoFuncGetDate(ExecState* exec, JSObject* thisObj, const List&)
1246 if (!thisObj->inherits(&DateInstance::info))
1247 return throwError(exec, TypeError);
1249 const bool utc = false;
1251 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1252 JSValue* v = thisDateObj->internalValue();
1253 double milli = v->toNumber(exec);
1257 GregorianDateTime t;
1258 thisDateObj->msToGregorianDateTime(milli, utc, t);
1259 return jsNumber(t.monthDay);
1262 JSValue* dateProtoFuncGetUTCDate(ExecState* exec, JSObject* thisObj, const List&)
1264 if (!thisObj->inherits(&DateInstance::info))
1265 return throwError(exec, TypeError);
1267 const bool utc = true;
1269 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1270 JSValue* v = thisDateObj->internalValue();
1271 double milli = v->toNumber(exec);
1275 GregorianDateTime t;
1276 thisDateObj->msToGregorianDateTime(milli, utc, t);
1277 return jsNumber(t.monthDay);
1280 JSValue* dateProtoFuncGetDay(ExecState* exec, JSObject* thisObj, const List&)
1282 if (!thisObj->inherits(&DateInstance::info))
1283 return throwError(exec, TypeError);
1285 const bool utc = false;
1287 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1288 JSValue* v = thisDateObj->internalValue();
1289 double milli = v->toNumber(exec);
1293 GregorianDateTime t;
1294 thisDateObj->msToGregorianDateTime(milli, utc, t);
1295 return jsNumber(t.weekDay);
1298 JSValue* dateProtoFuncGetUTCDay(ExecState* exec, JSObject* thisObj, const List&)
1300 if (!thisObj->inherits(&DateInstance::info))
1301 return throwError(exec, TypeError);
1303 const bool utc = true;
1305 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1306 JSValue* v = thisDateObj->internalValue();
1307 double milli = v->toNumber(exec);
1311 GregorianDateTime t;
1312 thisDateObj->msToGregorianDateTime(milli, utc, t);
1313 return jsNumber(t.weekDay);
1316 JSValue* dateProtoFuncGetHours(ExecState* exec, JSObject* thisObj, const List&)
1318 if (!thisObj->inherits(&DateInstance::info))
1319 return throwError(exec, TypeError);
1321 const bool utc = false;
1323 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1324 JSValue* v = thisDateObj->internalValue();
1325 double milli = v->toNumber(exec);
1329 GregorianDateTime t;
1330 thisDateObj->msToGregorianDateTime(milli, utc, t);
1331 return jsNumber(t.hour);
1334 JSValue* dateProtoFuncGetUTCHours(ExecState* exec, JSObject* thisObj, const List&)
1336 if (!thisObj->inherits(&DateInstance::info))
1337 return throwError(exec, TypeError);
1339 const bool utc = true;
1341 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1342 JSValue* v = thisDateObj->internalValue();
1343 double milli = v->toNumber(exec);
1347 GregorianDateTime t;
1348 thisDateObj->msToGregorianDateTime(milli, utc, t);
1349 return jsNumber(t.hour);
1352 JSValue* dateProtoFuncGetMinutes(ExecState* exec, JSObject* thisObj, const List&)
1354 if (!thisObj->inherits(&DateInstance::info))
1355 return throwError(exec, TypeError);
1357 const bool utc = false;
1359 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1360 JSValue* v = thisDateObj->internalValue();
1361 double milli = v->toNumber(exec);
1365 GregorianDateTime t;
1366 thisDateObj->msToGregorianDateTime(milli, utc, t);
1367 return jsNumber(t.minute);
1370 JSValue* dateProtoFuncGetUTCMinutes(ExecState* exec, JSObject* thisObj, const List&)
1372 if (!thisObj->inherits(&DateInstance::info))
1373 return throwError(exec, TypeError);
1375 const bool utc = true;
1377 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1378 JSValue* v = thisDateObj->internalValue();
1379 double milli = v->toNumber(exec);
1383 GregorianDateTime t;
1384 thisDateObj->msToGregorianDateTime(milli, utc, t);
1385 return jsNumber(t.minute);
1388 JSValue* dateProtoFuncGetSeconds(ExecState* exec, JSObject* thisObj, const List&)
1390 if (!thisObj->inherits(&DateInstance::info))
1391 return throwError(exec, TypeError);
1393 const bool utc = false;
1395 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1396 JSValue* v = thisDateObj->internalValue();
1397 double milli = v->toNumber(exec);
1401 GregorianDateTime t;
1402 thisDateObj->msToGregorianDateTime(milli, utc, t);
1403 return jsNumber(t.second);
1406 JSValue* dateProtoFuncGetUTCSeconds(ExecState* exec, JSObject* thisObj, const List&)
1408 if (!thisObj->inherits(&DateInstance::info))
1409 return throwError(exec, TypeError);
1411 const bool utc = true;
1413 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1414 JSValue* v = thisDateObj->internalValue();
1415 double milli = v->toNumber(exec);
1419 GregorianDateTime t;
1420 thisDateObj->msToGregorianDateTime(milli, utc, t);
1421 return jsNumber(t.second);
1424 JSValue* dateProtoFuncGetMilliSeconds(ExecState* exec, JSObject* thisObj, const List&)
1426 if (!thisObj->inherits(&DateInstance::info))
1427 return throwError(exec, TypeError);
1429 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1430 JSValue* v = thisDateObj->internalValue();
1431 double milli = v->toNumber(exec);
1435 double secs = floor(milli / msPerSecond);
1436 double ms = milli - secs * msPerSecond;
1437 return jsNumber(ms);
1440 JSValue* dateProtoFuncGetUTCMilliseconds(ExecState* exec, JSObject* thisObj, const List&)
1442 if (!thisObj->inherits(&DateInstance::info))
1443 return throwError(exec, TypeError);
1445 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1446 JSValue* v = thisDateObj->internalValue();
1447 double milli = v->toNumber(exec);
1451 double secs = floor(milli / msPerSecond);
1452 double ms = milli - secs * msPerSecond;
1453 return jsNumber(ms);
1456 JSValue* dateProtoFuncGetTimezoneOffset(ExecState* exec, JSObject* thisObj, const List&)
1458 if (!thisObj->inherits(&DateInstance::info))
1459 return throwError(exec, TypeError);
1461 const bool utc = false;
1463 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1464 JSValue* v = thisDateObj->internalValue();
1465 double milli = v->toNumber(exec);
1469 GregorianDateTime t;
1470 thisDateObj->msToGregorianDateTime(milli, utc, t);
1471 return jsNumber(-gmtoffset(t) / minutesPerHour);
1474 JSValue* dateProtoFuncSetTime(ExecState* exec, JSObject* thisObj, const List& args)
1476 if (!thisObj->inherits(&DateInstance::info))
1477 return throwError(exec, TypeError);
1479 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1481 double milli = timeClip(args[0]->toNumber(exec));
1482 JSValue* result = jsNumber(milli);
1483 thisDateObj->setInternalValue(result);
1487 static JSValue* setNewValueFromTimeArgs(ExecState* exec, JSObject* thisObj, const List& args, int numArgsToUse, bool inputIsUTC)
1489 if (!thisObj->inherits(&DateInstance::info))
1490 return throwError(exec, TypeError);
1492 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1493 JSValue* v = thisDateObj->internalValue();
1494 double milli = v->toNumber(exec);
1496 if (args.isEmpty() || isnan(milli)) {
1497 JSValue* result = jsNaN();
1498 thisDateObj->setInternalValue(result);
1502 double secs = floor(milli / msPerSecond);
1503 double ms = milli - secs * msPerSecond;
1505 GregorianDateTime t;
1506 thisDateObj->msToGregorianDateTime(milli, inputIsUTC, t);
1508 if (!fillStructuresUsingTimeArgs(exec, args, numArgsToUse, &ms, &t)) {
1509 JSValue* result = jsNaN();
1510 thisDateObj->setInternalValue(result);
1514 JSValue* result = jsNumber(gregorianDateTimeToMS(t, ms, inputIsUTC));
1515 thisDateObj->setInternalValue(result);
1519 static JSValue* setNewValueFromDateArgs(ExecState* exec, JSObject* thisObj, const List& args, int numArgsToUse, bool inputIsUTC)
1521 if (!thisObj->inherits(&DateInstance::info))
1522 return throwError(exec, TypeError);
1524 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1525 if (args.isEmpty()) {
1526 JSValue* result = jsNaN();
1527 thisDateObj->setInternalValue(result);
1531 JSValue* v = thisDateObj->internalValue();
1532 double milli = v->toNumber(exec);
1535 GregorianDateTime t;
1536 if (numArgsToUse == 3 && isnan(milli))
1537 // Based on ECMA 262 15.9.5.40 - .41 (set[UTC]FullYear)
1538 // the time must be reset to +0 if it is NaN.
1539 thisDateObj->msToGregorianDateTime(0, true, t);
1541 double secs = floor(milli / msPerSecond);
1542 ms = milli - secs * msPerSecond;
1543 thisDateObj->msToGregorianDateTime(milli, inputIsUTC, t);
1546 if (!fillStructuresUsingDateArgs(exec, args, numArgsToUse, &ms, &t)) {
1547 JSValue* result = jsNaN();
1548 thisDateObj->setInternalValue(result);
1552 JSValue* result = jsNumber(gregorianDateTimeToMS(t, ms, inputIsUTC));
1553 thisDateObj->setInternalValue(result);
1557 JSValue* dateProtoFuncSetMilliSeconds(ExecState* exec, JSObject* thisObj, const List& args)
1559 const bool inputIsUTC = false;
1560 return setNewValueFromTimeArgs(exec, thisObj, args, 1, inputIsUTC);
1563 JSValue* dateProtoFuncSetUTCMilliseconds(ExecState* exec, JSObject* thisObj, const List& args)
1565 const bool inputIsUTC = true;
1566 return setNewValueFromTimeArgs(exec, thisObj, args, 1, inputIsUTC);
1569 JSValue* dateProtoFuncSetSeconds(ExecState* exec, JSObject* thisObj, const List& args)
1571 const bool inputIsUTC = false;
1572 return setNewValueFromTimeArgs(exec, thisObj, args, 2, inputIsUTC);
1575 JSValue* dateProtoFuncSetUTCSeconds(ExecState* exec, JSObject* thisObj, const List& args)
1577 const bool inputIsUTC = true;
1578 return setNewValueFromTimeArgs(exec, thisObj, args, 2, inputIsUTC);
1581 JSValue* dateProtoFuncSetMinutes(ExecState* exec, JSObject* thisObj, const List& args)
1583 const bool inputIsUTC = false;
1584 return setNewValueFromTimeArgs(exec, thisObj, args, 3, inputIsUTC);
1587 JSValue* dateProtoFuncSetUTCMinutes(ExecState* exec, JSObject* thisObj, const List& args)
1589 const bool inputIsUTC = true;
1590 return setNewValueFromTimeArgs(exec, thisObj, args, 3, inputIsUTC);
1593 JSValue* dateProtoFuncSetHours(ExecState* exec, JSObject* thisObj, const List& args)
1595 const bool inputIsUTC = false;
1596 return setNewValueFromTimeArgs(exec, thisObj, args, 4, inputIsUTC);
1599 JSValue* dateProtoFuncSetUTCHours(ExecState* exec, JSObject* thisObj, const List& args)
1601 const bool inputIsUTC = true;
1602 return setNewValueFromTimeArgs(exec, thisObj, args, 4, inputIsUTC);
1605 JSValue* dateProtoFuncSetDate(ExecState* exec, JSObject* thisObj, const List& args)
1607 const bool inputIsUTC = false;
1608 return setNewValueFromDateArgs(exec, thisObj, args, 1, inputIsUTC);
1611 JSValue* dateProtoFuncSetUTCDate(ExecState* exec, JSObject* thisObj, const List& args)
1613 const bool inputIsUTC = true;
1614 return setNewValueFromDateArgs(exec, thisObj, args, 1, inputIsUTC);
1617 JSValue* dateProtoFuncSetMonth(ExecState* exec, JSObject* thisObj, const List& args)
1619 const bool inputIsUTC = false;
1620 return setNewValueFromDateArgs(exec, thisObj, args, 2, inputIsUTC);
1623 JSValue* dateProtoFuncSetUTCMonth(ExecState* exec, JSObject* thisObj, const List& args)
1625 const bool inputIsUTC = true;
1626 return setNewValueFromDateArgs(exec, thisObj, args, 2, inputIsUTC);
1629 JSValue* dateProtoFuncSetFullYear(ExecState* exec, JSObject* thisObj, const List& args)
1631 const bool inputIsUTC = false;
1632 return setNewValueFromDateArgs(exec, thisObj, args, 3, inputIsUTC);
1635 JSValue* dateProtoFuncSetUTCFullYear(ExecState* exec, JSObject* thisObj, const List& args)
1637 const bool inputIsUTC = true;
1638 return setNewValueFromDateArgs(exec, thisObj, args, 3, inputIsUTC);
1641 JSValue* dateProtoFuncSetYear(ExecState* exec, JSObject* thisObj, const List& args)
1643 if (!thisObj->inherits(&DateInstance::info))
1644 return throwError(exec, TypeError);
1646 const bool utc = false;
1648 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1649 if (args.isEmpty()) {
1650 JSValue* result = jsNaN();
1651 thisDateObj->setInternalValue(result);
1655 JSValue* v = thisDateObj->internalValue();
1656 double milli = v->toNumber(exec);
1659 GregorianDateTime t;
1661 // Based on ECMA 262 B.2.5 (setYear)
1662 // the time must be reset to +0 if it is NaN.
1663 thisDateObj->msToGregorianDateTime(0, true, t);
1665 double secs = floor(milli / msPerSecond);
1666 ms = milli - secs * msPerSecond;
1667 thisDateObj->msToGregorianDateTime(milli, utc, t);
1671 int32_t year = args[0]->toInt32(exec, ok);
1673 JSValue* result = jsNaN();
1674 thisDateObj->setInternalValue(result);
1678 t.year = (year > 99 || year < 0) ? year - 1900 : year;
1679 JSValue* result = jsNumber(gregorianDateTimeToMS(t, ms, utc));
1680 thisDateObj->setInternalValue(result);
1684 JSValue* dateProtoFuncGetYear(ExecState* exec, JSObject* thisObj, const List&)
1686 if (!thisObj->inherits(&DateInstance::info))
1687 return throwError(exec, TypeError);
1689 const bool utc = false;
1691 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1692 JSValue* v = thisDateObj->internalValue();
1693 double milli = v->toNumber(exec);
1697 GregorianDateTime t;
1698 thisDateObj->msToGregorianDateTime(milli, utc, t);
1700 // NOTE: IE returns the full year even in getYear.
1701 return jsNumber(t.year);