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);
99 static CFDateFormatterStyle styleFromArgString(const UString& string, CFDateFormatterStyle defaultStyle)
101 if (string == "short")
102 return kCFDateFormatterShortStyle;
103 if (string == "medium")
104 return kCFDateFormatterMediumStyle;
105 if (string == "long")
106 return kCFDateFormatterLongStyle;
107 if (string == "full")
108 return kCFDateFormatterFullStyle;
112 static UString formatLocaleDate(ExecState *exec, double time, bool includeDate, bool includeTime, const List &args)
114 CFDateFormatterStyle dateStyle = (includeDate ? kCFDateFormatterLongStyle : kCFDateFormatterNoStyle);
115 CFDateFormatterStyle timeStyle = (includeTime ? kCFDateFormatterLongStyle : kCFDateFormatterNoStyle);
117 bool useCustomFormat = false;
118 UString customFormatString;
120 UString arg0String = args[0]->toString(exec);
121 if (arg0String == "custom" && !args[1]->isUndefined()) {
122 useCustomFormat = true;
123 customFormatString = args[1]->toString(exec);
124 } else if (includeDate && includeTime && !args[1]->isUndefined()) {
125 dateStyle = styleFromArgString(arg0String, dateStyle);
126 timeStyle = styleFromArgString(args[1]->toString(exec), timeStyle);
127 } else if (includeDate && !args[0]->isUndefined()) {
128 dateStyle = styleFromArgString(arg0String, dateStyle);
129 } else if (includeTime && !args[0]->isUndefined()) {
130 timeStyle = styleFromArgString(arg0String, timeStyle);
133 CFLocaleRef locale = CFLocaleCopyCurrent();
134 CFDateFormatterRef formatter = CFDateFormatterCreate(0, locale, dateStyle, timeStyle);
137 if (useCustomFormat) {
138 CFStringRef customFormatCFString = CFStringCreateWithCharacters(0, (UniChar *)customFormatString.data(), customFormatString.size());
139 CFDateFormatterSetFormat(formatter, customFormatCFString);
140 CFRelease(customFormatCFString);
143 CFStringRef string = CFDateFormatterCreateStringWithAbsoluteTime(0, formatter, time - kCFAbsoluteTimeIntervalSince1970);
145 CFRelease(formatter);
147 // We truncate the string returned from CFDateFormatter if it's absurdly long (> 200 characters).
148 // That's not great error handling, but it just won't happen so it doesn't matter.
150 const size_t bufferLength = sizeof(buffer) / sizeof(buffer[0]);
151 size_t length = CFStringGetLength(string);
152 ASSERT(length <= bufferLength);
153 if (length > bufferLength)
154 length = bufferLength;
155 CFStringGetCharacters(string, CFRangeMake(0, length), reinterpret_cast<UniChar *>(buffer));
159 return UString(buffer, length);
164 enum LocaleDateTimeFormat { LocaleDateAndTime, LocaleDate, LocaleTime };
166 static JSCell* formatLocaleDate(const GregorianDateTime& gdt, const LocaleDateTimeFormat format)
168 static const char* formatStrings[] = {"%#c", "%#x", "%X"};
170 // Offset year if needed
171 struct tm localTM = gdt;
172 int year = gdt.year + 1900;
173 bool yearNeedsOffset = year < 1900 || year > 2038;
174 if (yearNeedsOffset) {
175 localTM.tm_year = equivalentYearForDST(year) - 1900;
179 const int bufsize=128;
180 char timebuffer[bufsize];
181 size_t ret = strftime(timebuffer, bufsize, formatStrings[format], &localTM);
186 // Copy original into the buffer
187 if (yearNeedsOffset && format != LocaleTime) {
188 static const int yearLen = 5; // FIXME will be a problem in the year 10,000
189 char yearString[yearLen];
191 snprintf(yearString, yearLen, "%d", localTM.tm_year + 1900);
192 char* yearLocation = strstr(timebuffer, yearString);
193 snprintf(yearString, yearLen, "%d", year);
195 strncpy(yearLocation, yearString, yearLen - 1);
198 return jsString(timebuffer);
201 #endif // PLATFORM(WIN_OS)
203 static UString formatDate(const GregorianDateTime &t)
206 snprintf(buffer, sizeof(buffer), "%s %s %02d %04d",
207 weekdayName[(t.weekDay + 6) % 7],
208 monthName[t.month], t.monthDay, t.year + 1900);
212 static UString formatDateUTCVariant(const GregorianDateTime &t)
215 snprintf(buffer, sizeof(buffer), "%s, %02d %s %04d",
216 weekdayName[(t.weekDay + 6) % 7],
217 t.monthDay, monthName[t.month], t.year + 1900);
221 static UString formatTime(const GregorianDateTime &t, bool utc)
225 snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d GMT", t.hour, t.minute, t.second);
227 int offset = abs(gmtoffset(t));
230 strftime(tzname, sizeof(tzname), "%Z", >m);
233 snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d GMT%c%02d%02d (%s)",
234 t.hour, t.minute, t.second,
235 gmtoffset(t) < 0 ? '-' : '+', offset / (60*60), (offset / 60) % 60, tzname);
237 snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d GMT%c%02d%02d",
238 t.hour, t.minute, t.second,
239 gmtoffset(t) < 0 ? '-' : '+', offset / (60*60), (offset / 60) % 60);
242 return UString(buffer);
245 // Converts a list of arguments sent to a Date member function into milliseconds, updating
246 // ms (representing milliseconds) and t (representing the rest of the date structure) appropriately.
248 // Format of member function: f([hour,] [min,] [sec,] [ms])
249 static bool fillStructuresUsingTimeArgs(ExecState* exec, const List& args, int maxArgs, double* ms, GregorianDateTime* t)
251 double milliseconds = 0;
254 int numArgs = args.size();
256 // JS allows extra trailing arguments -- ignore them
257 if (numArgs > maxArgs)
261 if (maxArgs >= 4 && idx < numArgs) {
263 milliseconds += args[idx++]->toInt32(exec, ok) * msPerHour;
267 if (maxArgs >= 3 && idx < numArgs && ok) {
269 milliseconds += args[idx++]->toInt32(exec, ok) * msPerMinute;
273 if (maxArgs >= 2 && idx < numArgs && ok) {
275 milliseconds += args[idx++]->toInt32(exec, ok) * msPerSecond;
283 double millis = args[idx]->toNumber(exec);
284 ok = isfinite(millis);
285 milliseconds += millis;
293 // Converts a list of arguments sent to a Date member function into years, months, and milliseconds, updating
294 // ms (representing milliseconds) and t (representing the rest of the date structure) appropriately.
296 // Format of member function: f([years,] [months,] [days])
297 static bool fillStructuresUsingDateArgs(ExecState *exec, const List &args, int maxArgs, double *ms, GregorianDateTime *t)
301 int numArgs = args.size();
303 // JS allows extra trailing arguments -- ignore them
304 if (numArgs > maxArgs)
308 if (maxArgs >= 3 && idx < numArgs)
309 t->year = args[idx++]->toInt32(exec, ok) - 1900;
312 if (maxArgs >= 2 && idx < numArgs && ok)
313 t->month = args[idx++]->toInt32(exec, ok);
316 if (idx < numArgs && ok) {
318 *ms += args[idx]->toInt32(exec, ok) * msPerDay;
324 // ------------------------------ DateInstance ------------------------------
326 const ClassInfo DateInstance::info = {"Date", 0, 0};
328 DateInstance::DateInstance(JSObject *proto)
329 : JSWrapperObject(proto)
333 bool DateInstance::getTime(GregorianDateTime &t, int &offset) const
335 double milli = internalValue()->getNumber();
339 msToGregorianDateTime(milli, false, t);
340 offset = gmtoffset(t);
344 bool DateInstance::getUTCTime(GregorianDateTime &t) const
346 double milli = internalValue()->getNumber();
350 msToGregorianDateTime(milli, true, t);
354 bool DateInstance::getTime(double &milli, int &offset) const
356 milli = internalValue()->getNumber();
361 msToGregorianDateTime(milli, false, t);
362 offset = gmtoffset(t);
366 bool DateInstance::getUTCTime(double &milli) const
368 milli = internalValue()->getNumber();
375 static inline bool isTime_tSigned()
377 time_t minusOne = (time_t)(-1);
381 // ------------------------------ DatePrototype -----------------------------
383 const ClassInfo DatePrototype::info = {"Date", &DateInstance::info, &dateTable};
385 /* Source for date_object.lut.h
386 FIXMEL We could use templates to simplify the UTC variants.
388 toString dateProtoFuncToString DontEnum|Function 0
389 toUTCString dateProtoFuncToUTCString DontEnum|Function 0
390 toDateString dateProtoFuncToDateString DontEnum|Function 0
391 toTimeString dateProtoFuncToTimeString DontEnum|Function 0
392 toLocaleString dateProtoFuncToLocaleString DontEnum|Function 0
393 toLocaleDateString dateProtoFuncToLocaleDateString DontEnum|Function 0
394 toLocaleTimeString dateProtoFuncToLocaleTimeString DontEnum|Function 0
395 valueOf dateProtoFuncValueOf DontEnum|Function 0
396 getTime dateProtoFuncGetTime DontEnum|Function 0
397 getFullYear dateProtoFuncGetFullYear DontEnum|Function 0
398 getUTCFullYear dateProtoFuncGetUTCFullYear DontEnum|Function 0
399 toGMTString dateProtoFuncToGMTString DontEnum|Function 0
400 getMonth dateProtoFuncGetMonth DontEnum|Function 0
401 getUTCMonth dateProtoFuncGetUTCMonth DontEnum|Function 0
402 getDate dateProtoFuncGetDate DontEnum|Function 0
403 getUTCDate dateProtoFuncGetUTCDate DontEnum|Function 0
404 getDay dateProtoFuncGetDay DontEnum|Function 0
405 getUTCDay dateProtoFuncGetUTCDay DontEnum|Function 0
406 getHours dateProtoFuncGetHours DontEnum|Function 0
407 getUTCHours dateProtoFuncGetUTCHours DontEnum|Function 0
408 getMinutes dateProtoFuncGetMinutes DontEnum|Function 0
409 getUTCMinutes dateProtoFuncGetUTCMinutes DontEnum|Function 0
410 getSeconds dateProtoFuncGetSeconds DontEnum|Function 0
411 getUTCSeconds dateProtoFuncGetUTCSeconds DontEnum|Function 0
412 getMilliseconds dateProtoFuncGetMilliSeconds DontEnum|Function 0
413 getUTCMilliseconds dateProtoFuncGetUTCMilliseconds DontEnum|Function 0
414 getTimezoneOffset dateProtoFuncGetTimezoneOffset DontEnum|Function 0
415 setTime dateProtoFuncSetTime DontEnum|Function 1
416 setMilliseconds dateProtoFuncSetMilliSeconds DontEnum|Function 1
417 setUTCMilliseconds dateProtoFuncSetUTCMilliseconds DontEnum|Function 1
418 setSeconds dateProtoFuncSetSeconds DontEnum|Function 2
419 setUTCSeconds dateProtoFuncSetUTCSeconds DontEnum|Function 2
420 setMinutes dateProtoFuncSetMinutes DontEnum|Function 3
421 setUTCMinutes dateProtoFuncSetUTCMinutes DontEnum|Function 3
422 setHours dateProtoFuncSetHours DontEnum|Function 4
423 setUTCHours dateProtoFuncSetUTCHours DontEnum|Function 4
424 setDate dateProtoFuncSetDate DontEnum|Function 1
425 setUTCDate dateProtoFuncSetUTCDate DontEnum|Function 1
426 setMonth dateProtoFuncSetMonth DontEnum|Function 2
427 setUTCMonth dateProtoFuncSetUTCMonth DontEnum|Function 2
428 setFullYear dateProtoFuncSetFullYear DontEnum|Function 3
429 setUTCFullYear dateProtoFuncSetUTCFullYear DontEnum|Function 3
430 setYear dateProtoFuncSetYear DontEnum|Function 1
431 getYear dateProtoFuncGetYear DontEnum|Function 0
436 DatePrototype::DatePrototype(ExecState *, ObjectPrototype *objectProto)
437 : DateInstance(objectProto)
439 setInternalValue(jsNaN());
440 // The constructor will be added later, after DateObjectImp has been built.
443 bool DatePrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
445 return getStaticFunctionSlot<JSObject>(exec, &dateTable, this, propertyName, slot);
448 // ------------------------------ DateObjectImp --------------------------------
450 // TODO: MakeTime (15.9.11.1) etc. ?
452 DateObjectImp::DateObjectImp(ExecState* exec, FunctionPrototype* funcProto, DatePrototype* dateProto)
453 : InternalFunctionImp(funcProto, dateProto->classInfo()->className)
455 static const Identifier* parsePropertyName = new Identifier("parse");
456 static const Identifier* UTCPropertyName = new Identifier("UTC");
458 putDirect(exec->propertyNames().prototype, dateProto, DontEnum|DontDelete|ReadOnly);
459 putDirectFunction(new DateObjectFuncImp(exec, funcProto, DateObjectFuncImp::Parse, 1, *parsePropertyName), DontEnum);
460 putDirectFunction(new DateObjectFuncImp(exec, funcProto, DateObjectFuncImp::UTC, 7, *UTCPropertyName), DontEnum);
461 putDirect(exec->propertyNames().length, 7, ReadOnly|DontDelete|DontEnum);
464 bool DateObjectImp::implementsConstruct() const
470 JSObject *DateObjectImp::construct(ExecState *exec, const List &args)
472 int numArgs = args.size();
476 if (numArgs == 0) { // new Date() ECMA 15.9.3.3
477 value = getCurrentUTCTime();
478 } else if (numArgs == 1) {
479 if (args[0]->isObject(&DateInstance::info))
480 value = static_cast<DateInstance*>(args[0])->internalValue()->toNumber(exec);
482 JSValue* primitive = args[0]->toPrimitive(exec);
483 if (primitive->isString())
484 value = parseDate(primitive->getString());
486 value = primitive->toNumber(exec);
489 if (isnan(args[0]->toNumber(exec))
490 || isnan(args[1]->toNumber(exec))
491 || (numArgs >= 3 && isnan(args[2]->toNumber(exec)))
492 || (numArgs >= 4 && isnan(args[3]->toNumber(exec)))
493 || (numArgs >= 5 && isnan(args[4]->toNumber(exec)))
494 || (numArgs >= 6 && isnan(args[5]->toNumber(exec)))
495 || (numArgs >= 7 && isnan(args[6]->toNumber(exec)))) {
499 int year = args[0]->toInt32(exec);
500 t.year = (year >= 0 && year <= 99) ? year : year - 1900;
501 t.month = args[1]->toInt32(exec);
502 t.monthDay = (numArgs >= 3) ? args[2]->toInt32(exec) : 1;
503 t.hour = args[3]->toInt32(exec);
504 t.minute = args[4]->toInt32(exec);
505 t.second = args[5]->toInt32(exec);
507 double ms = (numArgs >= 7) ? args[6]->toNumber(exec) : 0;
508 value = gregorianDateTimeToMS(t, ms, false);
512 DateInstance *ret = new DateInstance(exec->lexicalGlobalObject()->datePrototype());
513 ret->setInternalValue(jsNumber(timeClip(value)));
518 JSValue *DateObjectImp::callAsFunction(ExecState * /*exec*/, JSObject * /*thisObj*/, const List &/*args*/)
521 GregorianDateTime ts(*localtime(&t));
522 return jsString(formatDate(ts) + " " + formatTime(ts, false));
525 // ------------------------------ DateObjectFuncImp ----------------------------
527 DateObjectFuncImp::DateObjectFuncImp(ExecState* exec, FunctionPrototype* funcProto, int i, int len, const Identifier& name)
528 : InternalFunctionImp(funcProto, name), id(i)
530 putDirect(exec->propertyNames().length, len, DontDelete|ReadOnly|DontEnum);
534 JSValue *DateObjectFuncImp::callAsFunction(ExecState* exec, JSObject*, const List& args)
537 return jsNumber(parseDate(args[0]->toString(exec)));
541 if (isnan(args[0]->toNumber(exec))
542 || isnan(args[1]->toNumber(exec))
543 || (n >= 3 && isnan(args[2]->toNumber(exec)))
544 || (n >= 4 && isnan(args[3]->toNumber(exec)))
545 || (n >= 5 && isnan(args[4]->toNumber(exec)))
546 || (n >= 6 && isnan(args[5]->toNumber(exec)))
547 || (n >= 7 && isnan(args[6]->toNumber(exec)))) {
552 memset(&t, 0, sizeof(t));
553 int year = args[0]->toInt32(exec);
554 t.year = (year >= 0 && year <= 99) ? year : year - 1900;
555 t.month = args[1]->toInt32(exec);
556 t.monthDay = (n >= 3) ? args[2]->toInt32(exec) : 1;
557 t.hour = args[3]->toInt32(exec);
558 t.minute = args[4]->toInt32(exec);
559 t.second = args[5]->toInt32(exec);
560 double ms = (n >= 7) ? args[6]->toNumber(exec) : 0;
561 return jsNumber(gregorianDateTimeToMS(t, ms, true));
565 // -----------------------------------------------------------------------------
567 // Code originally from krfcdate.cpp, but we don't want to use kdecore, and we want double range.
569 static inline double ymdhmsToSeconds(long year, int mon, int day, int hour, int minute, int second)
571 double days = (day - 32075)
572 + floor(1461 * (year + 4800.0 + (mon - 14) / 12) / 4)
573 + 367 * (mon - 2 - (mon - 14) / 12 * 12) / 12
574 - floor(3 * ((year + 4900.0 + (mon - 14) / 12) / 100) / 4)
576 return ((days * hoursPerDay + hour) * minutesPerHour + minute) * secondsPerMinute + second;
579 // We follow the recommendation of RFC 2822 to consider all
580 // obsolete time zones not listed here equivalent to "-0000".
581 static const struct KnownZone {
582 #if !PLATFORM(WIN_OS)
600 inline static void skipSpacesAndComments(const char*& s)
605 if (!isASCIISpace(ch)) {
608 else if (ch == ')' && nesting > 0)
610 else if (nesting == 0)
617 // returns 0-11 (Jan-Dec); -1 on failure
618 static int findMonth(const char* monthStr)
622 for (int i = 0; i < 3; ++i) {
625 needle[i] = static_cast<char>(toASCIILower(*monthStr++));
628 const char *haystack = "janfebmaraprmayjunjulaugsepoctnovdec";
629 const char *str = strstr(haystack, needle);
631 int position = static_cast<int>(str - haystack);
632 if (position % 3 == 0)
638 static double parseDate(const UString &date)
640 // This parses a date in the form:
641 // Tuesday, 09-Nov-99 23:12:40 GMT
643 // Sat, 01-Jan-2000 08:00:00 GMT
645 // Sat, 01 Jan 2000 08:00:00 GMT
647 // 01 Jan 99 22:00 +0100 (exceptions in rfc822/rfc2822)
648 // ### non RFC formats, added for Javascript:
649 // [Wednesday] January 09 1999 23:12:40 GMT
650 // [Wednesday] January 09 23:12:40 GMT 1999
652 // We ignore the weekday.
654 CString dateCString = date.UTF8String();
655 const char *dateString = dateCString.c_str();
657 // Skip leading space
658 skipSpacesAndComments(dateString);
661 const char *wordStart = dateString;
662 // Check contents of first words if not number
663 while (*dateString && !isASCIIDigit(*dateString)) {
664 if (isASCIISpace(*dateString) || *dateString == '(') {
665 if (dateString - wordStart >= 3)
666 month = findMonth(wordStart);
667 skipSpacesAndComments(dateString);
668 wordStart = dateString;
673 // Missing delimiter between month and day (like "January29")?
674 if (month == -1 && wordStart != dateString)
675 month = findMonth(wordStart);
677 skipSpacesAndComments(dateString);
682 // ' 09-Nov-99 23:12:40 GMT'
685 long day = strtol(dateString, &newPosStr, 10);
688 dateString = newPosStr;
698 // ### where is the boundary and what happens below?
699 if (*dateString != '/')
701 // looks like a YYYY/MM/DD date
705 month = strtol(dateString, &newPosStr, 10) - 1;
708 dateString = newPosStr;
709 if (*dateString++ != '/' || !*dateString)
711 day = strtol(dateString, &newPosStr, 10);
714 dateString = newPosStr;
715 } else if (*dateString == '/' && month == -1) {
717 // This looks like a MM/DD/YYYY date, not an RFC date.
718 month = day - 1; // 0-based
719 day = strtol(dateString, &newPosStr, 10);
722 if (day < 1 || day > 31)
724 dateString = newPosStr;
725 if (*dateString == '/')
730 if (*dateString == '-')
733 skipSpacesAndComments(dateString);
735 if (*dateString == ',')
738 if (month == -1) { // not found yet
739 month = findMonth(dateString);
743 while (*dateString && *dateString != '-' && *dateString != ',' && !isASCIISpace(*dateString))
749 // '-99 23:12:40 GMT'
750 if (*dateString != '-' && *dateString != '/' && *dateString != ',' && !isASCIISpace(*dateString))
756 if (month < 0 || month > 11)
760 if (year <= 0 && *dateString) {
761 year = strtol(dateString, &newPosStr, 10);
766 // Don't fail if the time is missing.
771 dateString = newPosStr;
774 if (!(isASCIISpace(*newPosStr) || *newPosStr == ',')) {
775 if (*newPosStr != ':')
777 // There was no year; the number was the hour.
780 // in the normal case (we parsed the year), advance to the next number
781 dateString = ++newPosStr;
782 skipSpacesAndComments(dateString);
785 hour = strtol(dateString, &newPosStr, 10);
786 // Do not check for errno here since we want to continue
787 // even if errno was set becasue we are still looking
790 // Read a number? If not, this might be a timezone name.
791 if (newPosStr != dateString) {
792 dateString = newPosStr;
794 if (hour < 0 || hour > 23)
801 if (*dateString++ != ':')
804 minute = strtol(dateString, &newPosStr, 10);
807 dateString = newPosStr;
809 if (minute < 0 || minute > 59)
813 if (*dateString && *dateString != ':' && !isASCIISpace(*dateString))
816 // seconds are optional in rfc822 + rfc2822
817 if (*dateString ==':') {
820 second = strtol(dateString, &newPosStr, 10);
823 dateString = newPosStr;
825 if (second < 0 || second > 59)
829 skipSpacesAndComments(dateString);
831 if (strncasecmp(dateString, "AM", 2) == 0) {
837 skipSpacesAndComments(dateString);
838 } else if (strncasecmp(dateString, "PM", 2) == 0) {
844 skipSpacesAndComments(dateString);
852 // Don't fail if the time zone is missing.
853 // Some websites omit the time zone (4275206).
855 if (strncasecmp(dateString, "GMT", 3) == 0 || strncasecmp(dateString, "UTC", 3) == 0) {
860 if (*dateString == '+' || *dateString == '-') {
861 long o = strtol(dateString, &newPosStr, 10);
864 dateString = newPosStr;
866 if (o < -9959 || o > 9959)
869 int sgn = (o < 0) ? -1 : 1;
871 if (*dateString != ':') {
872 offset = ((o / 100) * 60 + (o % 100)) * sgn;
873 } else { // GMT+05:00
874 long o2 = strtol(dateString, &newPosStr, 10);
877 dateString = newPosStr;
878 offset = (o * 60 + o2) * sgn;
882 for (int i = 0; i < int(sizeof(known_zones) / sizeof(KnownZone)); i++) {
883 if (0 == strncasecmp(dateString, known_zones[i].tzName, strlen(known_zones[i].tzName))) {
884 offset = known_zones[i].tzOffset;
885 dateString += strlen(known_zones[i].tzName);
893 skipSpacesAndComments(dateString);
895 if (*dateString && year == -1) {
896 year = strtol(dateString, &newPosStr, 10);
899 dateString = newPosStr;
902 skipSpacesAndComments(dateString);
908 // Y2K: Handle 2 digit years.
909 if (year >= 0 && year < 100) {
916 // fall back to local timezone
919 memset(&t, 0, sizeof(tm));
922 t.year = year - 1900;
928 // Use our gregorianDateTimeToMS() rather than mktime() as the latter can't handle the full year range.
929 return gregorianDateTimeToMS(t, 0, false);
932 return (ymdhmsToSeconds(year, month + 1, day, hour, minute, second) - (offset * 60.0)) * msPerSecond;
935 double timeClip(double t)
939 if (fabs(t) > 8.64E15)
946 JSValue* dateProtoFuncToString(ExecState* exec, JSObject* thisObj, const List&)
948 if (!thisObj->inherits(&DateInstance::info))
949 return throwError(exec, TypeError);
951 const bool utc = false;
953 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
954 JSValue* v = thisDateObj->internalValue();
955 double milli = v->toNumber(exec);
957 return jsString("Invalid Date");
960 msToGregorianDateTime(milli, utc, t);
961 return jsString(formatDate(t) + " " + formatTime(t, utc));
964 JSValue* dateProtoFuncToUTCString(ExecState* exec, JSObject* thisObj, const List&)
966 if (!thisObj->inherits(&DateInstance::info))
967 return throwError(exec, TypeError);
969 const bool utc = true;
971 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
972 JSValue* v = thisDateObj->internalValue();
973 double milli = v->toNumber(exec);
975 return jsString("Invalid Date");
978 msToGregorianDateTime(milli, utc, t);
979 return jsString(formatDateUTCVariant(t) + " " + formatTime(t, utc));
982 JSValue* dateProtoFuncToDateString(ExecState* exec, JSObject* thisObj, const List&)
984 if (!thisObj->inherits(&DateInstance::info))
985 return throwError(exec, TypeError);
987 const bool utc = false;
989 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
990 JSValue* v = thisDateObj->internalValue();
991 double milli = v->toNumber(exec);
993 return jsString("Invalid Date");
996 msToGregorianDateTime(milli, utc, t);
997 return jsString(formatDate(t));
1000 JSValue* dateProtoFuncToTimeString(ExecState* exec, JSObject* thisObj, const List&)
1002 if (!thisObj->inherits(&DateInstance::info))
1003 return throwError(exec, TypeError);
1005 const bool utc = false;
1007 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1008 JSValue* v = thisDateObj->internalValue();
1009 double milli = v->toNumber(exec);
1011 return jsString("Invalid Date");
1013 GregorianDateTime t;
1014 msToGregorianDateTime(milli, utc, t);
1015 return jsString(formatTime(t, utc));
1018 JSValue* dateProtoFuncToLocaleString(ExecState* exec, JSObject* thisObj, const List& args)
1020 if (!thisObj->inherits(&DateInstance::info))
1021 return throwError(exec, TypeError);
1023 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1024 JSValue* v = thisDateObj->internalValue();
1025 double milli = v->toNumber(exec);
1027 return jsString("Invalid Date");
1030 double secs = floor(milli / msPerSecond);
1031 return jsString(formatLocaleDate(exec, secs, true, true, args));
1035 const bool utc = false;
1037 GregorianDateTime t;
1038 msToGregorianDateTime(milli, utc, t);
1039 return formatLocaleDate(t, LocaleDateAndTime);
1043 JSValue* dateProtoFuncToLocaleDateString(ExecState* exec, JSObject* thisObj, const List& args)
1045 if (!thisObj->inherits(&DateInstance::info))
1046 return throwError(exec, TypeError);
1048 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1049 JSValue* v = thisDateObj->internalValue();
1050 double milli = v->toNumber(exec);
1052 return jsString("Invalid Date");
1055 double secs = floor(milli / msPerSecond);
1056 return jsString(formatLocaleDate(exec, secs, true, false, args));
1060 const bool utc = false;
1062 GregorianDateTime t;
1063 msToGregorianDateTime(milli, utc, t);
1064 return formatLocaleDate(t, LocaleDate);
1068 JSValue* dateProtoFuncToLocaleTimeString(ExecState* exec, JSObject* thisObj, const List& args)
1070 if (!thisObj->inherits(&DateInstance::info))
1071 return throwError(exec, TypeError);
1073 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1074 JSValue* v = thisDateObj->internalValue();
1075 double milli = v->toNumber(exec);
1077 return jsString("Invalid Date");
1080 double secs = floor(milli / msPerSecond);
1081 return jsString(formatLocaleDate(exec, secs, false, true, args));
1085 const bool utc = false;
1087 GregorianDateTime t;
1088 msToGregorianDateTime(milli, utc, t);
1089 return formatLocaleDate(t, LocaleTime);
1093 JSValue* dateProtoFuncValueOf(ExecState* exec, JSObject* thisObj, const List&)
1095 if (!thisObj->inherits(&DateInstance::info))
1096 return throwError(exec, TypeError);
1098 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1099 JSValue* v = thisDateObj->internalValue();
1100 double milli = v->toNumber(exec);
1104 return jsNumber(milli);
1107 JSValue* dateProtoFuncGetTime(ExecState* exec, JSObject* thisObj, const List&)
1109 if (!thisObj->inherits(&DateInstance::info))
1110 return throwError(exec, TypeError);
1112 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1113 JSValue* v = thisDateObj->internalValue();
1114 double milli = v->toNumber(exec);
1118 return jsNumber(milli);
1121 JSValue* dateProtoFuncGetFullYear(ExecState* exec, JSObject* thisObj, const List&)
1123 if (!thisObj->inherits(&DateInstance::info))
1124 return throwError(exec, TypeError);
1126 const bool utc = false;
1128 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1129 JSValue* v = thisDateObj->internalValue();
1130 double milli = v->toNumber(exec);
1134 GregorianDateTime t;
1135 msToGregorianDateTime(milli, utc, t);
1136 return jsNumber(1900 + t.year);
1139 JSValue* dateProtoFuncGetUTCFullYear(ExecState* exec, JSObject* thisObj, const List&)
1141 if (!thisObj->inherits(&DateInstance::info))
1142 return throwError(exec, TypeError);
1144 const bool utc = true;
1146 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1147 JSValue* v = thisDateObj->internalValue();
1148 double milli = v->toNumber(exec);
1152 GregorianDateTime t;
1153 msToGregorianDateTime(milli, utc, t);
1154 return jsNumber(1900 + t.year);
1157 JSValue* dateProtoFuncToGMTString(ExecState* exec, JSObject* thisObj, const List&)
1159 if (!thisObj->inherits(&DateInstance::info))
1160 return throwError(exec, TypeError);
1162 const bool utc = true;
1164 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1165 JSValue* v = thisDateObj->internalValue();
1166 double milli = v->toNumber(exec);
1168 return jsString("Invalid Date");
1170 GregorianDateTime t;
1171 msToGregorianDateTime(milli, utc, t);
1172 return jsString(formatDateUTCVariant(t) + " " + formatTime(t, utc));
1175 JSValue* dateProtoFuncGetMonth(ExecState* exec, JSObject* thisObj, const List&)
1177 if (!thisObj->inherits(&DateInstance::info))
1178 return throwError(exec, TypeError);
1180 const bool utc = false;
1182 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1183 JSValue* v = thisDateObj->internalValue();
1184 double milli = v->toNumber(exec);
1188 GregorianDateTime t;
1189 msToGregorianDateTime(milli, utc, t);
1190 return jsNumber(t.month);
1193 JSValue* dateProtoFuncGetUTCMonth(ExecState* exec, JSObject* thisObj, const List&)
1195 if (!thisObj->inherits(&DateInstance::info))
1196 return throwError(exec, TypeError);
1198 const bool utc = true;
1200 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1201 JSValue* v = thisDateObj->internalValue();
1202 double milli = v->toNumber(exec);
1206 GregorianDateTime t;
1207 msToGregorianDateTime(milli, utc, t);
1208 return jsNumber(t.month);
1211 JSValue* dateProtoFuncGetDate(ExecState* exec, JSObject* thisObj, const List&)
1213 if (!thisObj->inherits(&DateInstance::info))
1214 return throwError(exec, TypeError);
1216 const bool utc = false;
1218 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1219 JSValue* v = thisDateObj->internalValue();
1220 double milli = v->toNumber(exec);
1224 GregorianDateTime t;
1225 msToGregorianDateTime(milli, utc, t);
1226 return jsNumber(t.monthDay);
1229 JSValue* dateProtoFuncGetUTCDate(ExecState* exec, JSObject* thisObj, const List&)
1231 if (!thisObj->inherits(&DateInstance::info))
1232 return throwError(exec, TypeError);
1234 const bool utc = true;
1236 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1237 JSValue* v = thisDateObj->internalValue();
1238 double milli = v->toNumber(exec);
1242 GregorianDateTime t;
1243 msToGregorianDateTime(milli, utc, t);
1244 return jsNumber(t.monthDay);
1247 JSValue* dateProtoFuncGetDay(ExecState* exec, JSObject* thisObj, const List&)
1249 if (!thisObj->inherits(&DateInstance::info))
1250 return throwError(exec, TypeError);
1252 const bool utc = false;
1254 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1255 JSValue* v = thisDateObj->internalValue();
1256 double milli = v->toNumber(exec);
1260 GregorianDateTime t;
1261 msToGregorianDateTime(milli, utc, t);
1262 return jsNumber(t.weekDay);
1265 JSValue* dateProtoFuncGetUTCDay(ExecState* exec, JSObject* thisObj, const List&)
1267 if (!thisObj->inherits(&DateInstance::info))
1268 return throwError(exec, TypeError);
1270 const bool utc = true;
1272 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1273 JSValue* v = thisDateObj->internalValue();
1274 double milli = v->toNumber(exec);
1278 GregorianDateTime t;
1279 msToGregorianDateTime(milli, utc, t);
1280 return jsNumber(t.weekDay);
1283 JSValue* dateProtoFuncGetHours(ExecState* exec, JSObject* thisObj, const List&)
1285 if (!thisObj->inherits(&DateInstance::info))
1286 return throwError(exec, TypeError);
1288 const bool utc = false;
1290 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1291 JSValue* v = thisDateObj->internalValue();
1292 double milli = v->toNumber(exec);
1296 GregorianDateTime t;
1297 msToGregorianDateTime(milli, utc, t);
1298 return jsNumber(t.hour);
1301 JSValue* dateProtoFuncGetUTCHours(ExecState* exec, JSObject* thisObj, const List&)
1303 if (!thisObj->inherits(&DateInstance::info))
1304 return throwError(exec, TypeError);
1306 const bool utc = true;
1308 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1309 JSValue* v = thisDateObj->internalValue();
1310 double milli = v->toNumber(exec);
1314 GregorianDateTime t;
1315 msToGregorianDateTime(milli, utc, t);
1316 return jsNumber(t.hour);
1319 JSValue* dateProtoFuncGetMinutes(ExecState* exec, JSObject* thisObj, const List&)
1321 if (!thisObj->inherits(&DateInstance::info))
1322 return throwError(exec, TypeError);
1324 const bool utc = false;
1326 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1327 JSValue* v = thisDateObj->internalValue();
1328 double milli = v->toNumber(exec);
1332 GregorianDateTime t;
1333 msToGregorianDateTime(milli, utc, t);
1334 return jsNumber(t.minute);
1337 JSValue* dateProtoFuncGetUTCMinutes(ExecState* exec, JSObject* thisObj, const List&)
1339 if (!thisObj->inherits(&DateInstance::info))
1340 return throwError(exec, TypeError);
1342 const bool utc = true;
1344 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1345 JSValue* v = thisDateObj->internalValue();
1346 double milli = v->toNumber(exec);
1350 GregorianDateTime t;
1351 msToGregorianDateTime(milli, utc, t);
1352 return jsNumber(t.minute);
1355 JSValue* dateProtoFuncGetSeconds(ExecState* exec, JSObject* thisObj, const List&)
1357 if (!thisObj->inherits(&DateInstance::info))
1358 return throwError(exec, TypeError);
1360 const bool utc = false;
1362 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1363 JSValue* v = thisDateObj->internalValue();
1364 double milli = v->toNumber(exec);
1368 GregorianDateTime t;
1369 msToGregorianDateTime(milli, utc, t);
1370 return jsNumber(t.second);
1373 JSValue* dateProtoFuncGetUTCSeconds(ExecState* exec, JSObject* thisObj, const List&)
1375 if (!thisObj->inherits(&DateInstance::info))
1376 return throwError(exec, TypeError);
1378 const bool utc = true;
1380 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1381 JSValue* v = thisDateObj->internalValue();
1382 double milli = v->toNumber(exec);
1386 GregorianDateTime t;
1387 msToGregorianDateTime(milli, utc, t);
1388 return jsNumber(t.second);
1391 JSValue* dateProtoFuncGetMilliSeconds(ExecState* exec, JSObject* thisObj, const List&)
1393 if (!thisObj->inherits(&DateInstance::info))
1394 return throwError(exec, TypeError);
1396 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1397 JSValue* v = thisDateObj->internalValue();
1398 double milli = v->toNumber(exec);
1402 double secs = floor(milli / msPerSecond);
1403 double ms = milli - secs * msPerSecond;
1404 return jsNumber(ms);
1407 JSValue* dateProtoFuncGetUTCMilliseconds(ExecState* exec, JSObject* thisObj, const List&)
1409 if (!thisObj->inherits(&DateInstance::info))
1410 return throwError(exec, TypeError);
1412 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1413 JSValue* v = thisDateObj->internalValue();
1414 double milli = v->toNumber(exec);
1418 double secs = floor(milli / msPerSecond);
1419 double ms = milli - secs * msPerSecond;
1420 return jsNumber(ms);
1423 JSValue* dateProtoFuncGetTimezoneOffset(ExecState* exec, JSObject* thisObj, const List&)
1425 if (!thisObj->inherits(&DateInstance::info))
1426 return throwError(exec, TypeError);
1428 const bool utc = false;
1430 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1431 JSValue* v = thisDateObj->internalValue();
1432 double milli = v->toNumber(exec);
1436 GregorianDateTime t;
1437 msToGregorianDateTime(milli, utc, t);
1438 return jsNumber(-gmtoffset(t) / minutesPerHour);
1441 JSValue* dateProtoFuncSetTime(ExecState* exec, JSObject* thisObj, const List& args)
1443 if (!thisObj->inherits(&DateInstance::info))
1444 return throwError(exec, TypeError);
1446 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1448 double milli = timeClip(args[0]->toNumber(exec));
1449 JSValue* result = jsNumber(milli);
1450 thisDateObj->setInternalValue(result);
1454 static JSValue* setNewValueFromTimeArgs(ExecState* exec, JSObject* thisObj, const List& args, int numArgsToUse, bool inputIsUTC)
1456 if (!thisObj->inherits(&DateInstance::info))
1457 return throwError(exec, TypeError);
1459 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1460 JSValue* v = thisDateObj->internalValue();
1461 double milli = v->toNumber(exec);
1463 if (args.isEmpty() || isnan(milli)) {
1464 JSValue* result = jsNaN();
1465 thisDateObj->setInternalValue(result);
1469 double secs = floor(milli / msPerSecond);
1470 double ms = milli - secs * msPerSecond;
1472 GregorianDateTime t;
1473 msToGregorianDateTime(milli, inputIsUTC, t);
1475 if (!fillStructuresUsingTimeArgs(exec, args, numArgsToUse, &ms, &t)) {
1476 JSValue* result = jsNaN();
1477 thisDateObj->setInternalValue(result);
1481 JSValue* result = jsNumber(gregorianDateTimeToMS(t, ms, inputIsUTC));
1482 thisDateObj->setInternalValue(result);
1486 static JSValue* setNewValueFromDateArgs(ExecState* exec, JSObject* thisObj, const List& args, int numArgsToUse, bool inputIsUTC)
1488 if (!thisObj->inherits(&DateInstance::info))
1489 return throwError(exec, TypeError);
1491 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1492 if (args.isEmpty()) {
1493 JSValue* result = jsNaN();
1494 thisDateObj->setInternalValue(result);
1498 JSValue* v = thisDateObj->internalValue();
1499 double milli = v->toNumber(exec);
1502 GregorianDateTime t;
1503 if (numArgsToUse == 3 && isnan(milli))
1504 // Based on ECMA 262 15.9.5.40 - .41 (set[UTC]FullYear)
1505 // the time must be reset to +0 if it is NaN.
1506 msToGregorianDateTime(0, true, t);
1508 double secs = floor(milli / msPerSecond);
1509 ms = milli - secs * msPerSecond;
1510 msToGregorianDateTime(milli, inputIsUTC, t);
1513 if (!fillStructuresUsingDateArgs(exec, args, numArgsToUse, &ms, &t)) {
1514 JSValue* result = jsNaN();
1515 thisDateObj->setInternalValue(result);
1519 JSValue* result = jsNumber(gregorianDateTimeToMS(t, ms, inputIsUTC));
1520 thisDateObj->setInternalValue(result);
1524 JSValue* dateProtoFuncSetMilliSeconds(ExecState* exec, JSObject* thisObj, const List& args)
1526 const bool inputIsUTC = false;
1527 return setNewValueFromTimeArgs(exec, thisObj, args, 1, inputIsUTC);
1530 JSValue* dateProtoFuncSetUTCMilliseconds(ExecState* exec, JSObject* thisObj, const List& args)
1532 const bool inputIsUTC = true;
1533 return setNewValueFromTimeArgs(exec, thisObj, args, 1, inputIsUTC);
1536 JSValue* dateProtoFuncSetSeconds(ExecState* exec, JSObject* thisObj, const List& args)
1538 const bool inputIsUTC = false;
1539 return setNewValueFromTimeArgs(exec, thisObj, args, 2, inputIsUTC);
1542 JSValue* dateProtoFuncSetUTCSeconds(ExecState* exec, JSObject* thisObj, const List& args)
1544 const bool inputIsUTC = true;
1545 return setNewValueFromTimeArgs(exec, thisObj, args, 2, inputIsUTC);
1548 JSValue* dateProtoFuncSetMinutes(ExecState* exec, JSObject* thisObj, const List& args)
1550 const bool inputIsUTC = false;
1551 return setNewValueFromTimeArgs(exec, thisObj, args, 3, inputIsUTC);
1554 JSValue* dateProtoFuncSetUTCMinutes(ExecState* exec, JSObject* thisObj, const List& args)
1556 const bool inputIsUTC = true;
1557 return setNewValueFromTimeArgs(exec, thisObj, args, 3, inputIsUTC);
1560 JSValue* dateProtoFuncSetHours(ExecState* exec, JSObject* thisObj, const List& args)
1562 const bool inputIsUTC = false;
1563 return setNewValueFromTimeArgs(exec, thisObj, args, 4, inputIsUTC);
1566 JSValue* dateProtoFuncSetUTCHours(ExecState* exec, JSObject* thisObj, const List& args)
1568 const bool inputIsUTC = true;
1569 return setNewValueFromTimeArgs(exec, thisObj, args, 4, inputIsUTC);
1572 JSValue* dateProtoFuncSetDate(ExecState* exec, JSObject* thisObj, const List& args)
1574 const bool inputIsUTC = false;
1575 return setNewValueFromDateArgs(exec, thisObj, args, 1, inputIsUTC);
1578 JSValue* dateProtoFuncSetUTCDate(ExecState* exec, JSObject* thisObj, const List& args)
1580 const bool inputIsUTC = true;
1581 return setNewValueFromDateArgs(exec, thisObj, args, 1, inputIsUTC);
1584 JSValue* dateProtoFuncSetMonth(ExecState* exec, JSObject* thisObj, const List& args)
1586 const bool inputIsUTC = false;
1587 return setNewValueFromDateArgs(exec, thisObj, args, 2, inputIsUTC);
1590 JSValue* dateProtoFuncSetUTCMonth(ExecState* exec, JSObject* thisObj, const List& args)
1592 const bool inputIsUTC = true;
1593 return setNewValueFromDateArgs(exec, thisObj, args, 2, inputIsUTC);
1596 JSValue* dateProtoFuncSetFullYear(ExecState* exec, JSObject* thisObj, const List& args)
1598 const bool inputIsUTC = false;
1599 return setNewValueFromDateArgs(exec, thisObj, args, 3, inputIsUTC);
1602 JSValue* dateProtoFuncSetUTCFullYear(ExecState* exec, JSObject* thisObj, const List& args)
1604 const bool inputIsUTC = true;
1605 return setNewValueFromDateArgs(exec, thisObj, args, 3, inputIsUTC);
1608 JSValue* dateProtoFuncSetYear(ExecState* exec, JSObject* thisObj, const List& args)
1610 if (!thisObj->inherits(&DateInstance::info))
1611 return throwError(exec, TypeError);
1613 const bool utc = false;
1615 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1616 if (args.isEmpty()) {
1617 JSValue* result = jsNaN();
1618 thisDateObj->setInternalValue(result);
1622 JSValue* v = thisDateObj->internalValue();
1623 double milli = v->toNumber(exec);
1626 GregorianDateTime t;
1628 // Based on ECMA 262 B.2.5 (setYear)
1629 // the time must be reset to +0 if it is NaN.
1630 msToGregorianDateTime(0, true, t);
1632 double secs = floor(milli / msPerSecond);
1633 ms = milli - secs * msPerSecond;
1634 msToGregorianDateTime(milli, utc, t);
1638 int32_t year = args[0]->toInt32(exec, ok);
1640 JSValue* result = jsNaN();
1641 thisDateObj->setInternalValue(result);
1645 t.year = (year > 99 || year < 0) ? year - 1900 : year;
1646 JSValue* result = jsNumber(gregorianDateTimeToMS(t, ms, utc));
1647 thisDateObj->setInternalValue(result);
1651 JSValue* dateProtoFuncGetYear(ExecState* exec, JSObject* thisObj, const List&)
1653 if (!thisObj->inherits(&DateInstance::info))
1654 return throwError(exec, TypeError);
1656 const bool utc = false;
1658 DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
1659 JSValue* v = thisDateObj->internalValue();
1660 double milli = v->toNumber(exec);
1664 GregorianDateTime t;
1665 msToGregorianDateTime(milli, utc, t);
1667 // NOTE: IE returns the full year even in getYear.
1668 return jsNumber(t.year);