1708d444e9cdaca14d02a670488f530f90165545
[WebKit-https.git] / JavaScriptCore / runtime / DatePrototype.cpp
1 /*
2  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3  *  Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
4  *  Copyright (C) 2008, 2009 Torch Mobile, Inc. All rights reserved.
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Lesser General Public
8  *  License as published by the Free Software Foundation; either
9  *  version 2 of the License, or (at your option) any later version.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public
17  *  License along with this library; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
19  *  USA
20  *
21  */
22
23 #include "config.h"
24 #include "DatePrototype.h"
25
26 #include "DateConversion.h"
27 #include "Error.h"
28 #include "JSString.h"
29 #include "ObjectPrototype.h"
30 #include "DateInstance.h"
31 #include <float.h>
32
33 #if !PLATFORM(MAC) && HAVE(LANGINFO_H)
34 #include <langinfo.h>
35 #endif
36
37 #include <limits.h>
38 #include <locale.h>
39 #include <math.h>
40 #include <time.h>
41 #include <wtf/Assertions.h>
42 #include <wtf/DateMath.h>
43 #include <wtf/MathExtras.h>
44 #include <wtf/StringExtras.h>
45 #include <wtf/UnusedParam.h>
46
47 #if HAVE(SYS_PARAM_H)
48 #include <sys/param.h>
49 #endif
50
51 #if HAVE(SYS_TIME_H)
52 #include <sys/time.h>
53 #endif
54
55 #if HAVE(SYS_TIMEB_H)
56 #include <sys/timeb.h>
57 #endif
58
59 #if PLATFORM(MAC)
60 #include <CoreFoundation/CoreFoundation.h>
61 #endif
62
63 #if PLATFORM(WINCE) && !PLATFORM(QT)
64 extern "C" size_t strftime(char * const s, const size_t maxsize, const char * const format, const struct tm * const t); //provided by libce
65 #endif
66
67 using namespace WTF;
68
69 namespace JSC {
70
71 ASSERT_CLASS_FITS_IN_CELL(DatePrototype);
72
73 static JSValue JSC_HOST_CALL dateProtoFuncGetDate(ExecState*, JSObject*, JSValue, const ArgList&);
74 static JSValue JSC_HOST_CALL dateProtoFuncGetDay(ExecState*, JSObject*, JSValue, const ArgList&);
75 static JSValue JSC_HOST_CALL dateProtoFuncGetFullYear(ExecState*, JSObject*, JSValue, const ArgList&);
76 static JSValue JSC_HOST_CALL dateProtoFuncGetHours(ExecState*, JSObject*, JSValue, const ArgList&);
77 static JSValue JSC_HOST_CALL dateProtoFuncGetMilliSeconds(ExecState*, JSObject*, JSValue, const ArgList&);
78 static JSValue JSC_HOST_CALL dateProtoFuncGetMinutes(ExecState*, JSObject*, JSValue, const ArgList&);
79 static JSValue JSC_HOST_CALL dateProtoFuncGetMonth(ExecState*, JSObject*, JSValue, const ArgList&);
80 static JSValue JSC_HOST_CALL dateProtoFuncGetSeconds(ExecState*, JSObject*, JSValue, const ArgList&);
81 static JSValue JSC_HOST_CALL dateProtoFuncGetTime(ExecState*, JSObject*, JSValue, const ArgList&);
82 static JSValue JSC_HOST_CALL dateProtoFuncGetTimezoneOffset(ExecState*, JSObject*, JSValue, const ArgList&);
83 static JSValue JSC_HOST_CALL dateProtoFuncGetUTCDate(ExecState*, JSObject*, JSValue, const ArgList&);
84 static JSValue JSC_HOST_CALL dateProtoFuncGetUTCDay(ExecState*, JSObject*, JSValue, const ArgList&);
85 static JSValue JSC_HOST_CALL dateProtoFuncGetUTCFullYear(ExecState*, JSObject*, JSValue, const ArgList&);
86 static JSValue JSC_HOST_CALL dateProtoFuncGetUTCHours(ExecState*, JSObject*, JSValue, const ArgList&);
87 static JSValue JSC_HOST_CALL dateProtoFuncGetUTCMilliseconds(ExecState*, JSObject*, JSValue, const ArgList&);
88 static JSValue JSC_HOST_CALL dateProtoFuncGetUTCMinutes(ExecState*, JSObject*, JSValue, const ArgList&);
89 static JSValue JSC_HOST_CALL dateProtoFuncGetUTCMonth(ExecState*, JSObject*, JSValue, const ArgList&);
90 static JSValue JSC_HOST_CALL dateProtoFuncGetUTCSeconds(ExecState*, JSObject*, JSValue, const ArgList&);
91 static JSValue JSC_HOST_CALL dateProtoFuncGetYear(ExecState*, JSObject*, JSValue, const ArgList&);
92 static JSValue JSC_HOST_CALL dateProtoFuncSetDate(ExecState*, JSObject*, JSValue, const ArgList&);
93 static JSValue JSC_HOST_CALL dateProtoFuncSetFullYear(ExecState*, JSObject*, JSValue, const ArgList&);
94 static JSValue JSC_HOST_CALL dateProtoFuncSetHours(ExecState*, JSObject*, JSValue, const ArgList&);
95 static JSValue JSC_HOST_CALL dateProtoFuncSetMilliSeconds(ExecState*, JSObject*, JSValue, const ArgList&);
96 static JSValue JSC_HOST_CALL dateProtoFuncSetMinutes(ExecState*, JSObject*, JSValue, const ArgList&);
97 static JSValue JSC_HOST_CALL dateProtoFuncSetMonth(ExecState*, JSObject*, JSValue, const ArgList&);
98 static JSValue JSC_HOST_CALL dateProtoFuncSetSeconds(ExecState*, JSObject*, JSValue, const ArgList&);
99 static JSValue JSC_HOST_CALL dateProtoFuncSetTime(ExecState*, JSObject*, JSValue, const ArgList&);
100 static JSValue JSC_HOST_CALL dateProtoFuncSetUTCDate(ExecState*, JSObject*, JSValue, const ArgList&);
101 static JSValue JSC_HOST_CALL dateProtoFuncSetUTCFullYear(ExecState*, JSObject*, JSValue, const ArgList&);
102 static JSValue JSC_HOST_CALL dateProtoFuncSetUTCHours(ExecState*, JSObject*, JSValue, const ArgList&);
103 static JSValue JSC_HOST_CALL dateProtoFuncSetUTCMilliseconds(ExecState*, JSObject*, JSValue, const ArgList&);
104 static JSValue JSC_HOST_CALL dateProtoFuncSetUTCMinutes(ExecState*, JSObject*, JSValue, const ArgList&);
105 static JSValue JSC_HOST_CALL dateProtoFuncSetUTCMonth(ExecState*, JSObject*, JSValue, const ArgList&);
106 static JSValue JSC_HOST_CALL dateProtoFuncSetUTCSeconds(ExecState*, JSObject*, JSValue, const ArgList&);
107 static JSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState*, JSObject*, JSValue, const ArgList&);
108 static JSValue JSC_HOST_CALL dateProtoFuncToDateString(ExecState*, JSObject*, JSValue, const ArgList&);
109 static JSValue JSC_HOST_CALL dateProtoFuncToGMTString(ExecState*, JSObject*, JSValue, const ArgList&);
110 static JSValue JSC_HOST_CALL dateProtoFuncToLocaleDateString(ExecState*, JSObject*, JSValue, const ArgList&);
111 static JSValue JSC_HOST_CALL dateProtoFuncToLocaleString(ExecState*, JSObject*, JSValue, const ArgList&);
112 static JSValue JSC_HOST_CALL dateProtoFuncToLocaleTimeString(ExecState*, JSObject*, JSValue, const ArgList&);
113 static JSValue JSC_HOST_CALL dateProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&);
114 static JSValue JSC_HOST_CALL dateProtoFuncToTimeString(ExecState*, JSObject*, JSValue, const ArgList&);
115 static JSValue JSC_HOST_CALL dateProtoFuncToUTCString(ExecState*, JSObject*, JSValue, const ArgList&);
116 static JSValue JSC_HOST_CALL dateProtoFuncToISOString(ExecState*, JSObject*, JSValue, const ArgList&);
117
118 static JSValue JSC_HOST_CALL dateProtoFuncToJSON(ExecState*, JSObject*, JSValue, const ArgList&);
119
120 }
121
122 #include "DatePrototype.lut.h"
123
124 namespace JSC {
125
126 enum LocaleDateTimeFormat { LocaleDateAndTime, LocaleDate, LocaleTime };
127  
128 #if PLATFORM(MAC)
129
130 // FIXME: Since this is superior to the strftime-based version, why limit this to PLATFORM(MAC)?
131 // Instead we should consider using this whenever PLATFORM(CF) is true.
132
133 static CFDateFormatterStyle styleFromArgString(const UString& string, CFDateFormatterStyle defaultStyle)
134 {
135     if (string == "short")
136         return kCFDateFormatterShortStyle;
137     if (string == "medium")
138         return kCFDateFormatterMediumStyle;
139     if (string == "long")
140         return kCFDateFormatterLongStyle;
141     if (string == "full")
142         return kCFDateFormatterFullStyle;
143     return defaultStyle;
144 }
145
146 static JSCell* formatLocaleDate(ExecState* exec, DateInstance*, double timeInMilliseconds, LocaleDateTimeFormat format, const ArgList& args)
147 {
148     CFDateFormatterStyle dateStyle = (format != LocaleTime ? kCFDateFormatterLongStyle : kCFDateFormatterNoStyle);
149     CFDateFormatterStyle timeStyle = (format != LocaleDate ? kCFDateFormatterLongStyle : kCFDateFormatterNoStyle);
150
151     bool useCustomFormat = false;
152     UString customFormatString;
153
154     UString arg0String = args.at(0).toString(exec);
155     if (arg0String == "custom" && !args.at(1).isUndefined()) {
156         useCustomFormat = true;
157         customFormatString = args.at(1).toString(exec);
158     } else if (format == LocaleDateAndTime && !args.at(1).isUndefined()) {
159         dateStyle = styleFromArgString(arg0String, dateStyle);
160         timeStyle = styleFromArgString(args.at(1).toString(exec), timeStyle);
161     } else if (format != LocaleTime && !args.at(0).isUndefined())
162         dateStyle = styleFromArgString(arg0String, dateStyle);
163     else if (format != LocaleDate && !args.at(0).isUndefined())
164         timeStyle = styleFromArgString(arg0String, timeStyle);
165
166     CFLocaleRef locale = CFLocaleCopyCurrent();
167     CFDateFormatterRef formatter = CFDateFormatterCreate(0, locale, dateStyle, timeStyle);
168     CFRelease(locale);
169
170     if (useCustomFormat) {
171         CFStringRef customFormatCFString = CFStringCreateWithCharacters(0, customFormatString.data(), customFormatString.size());
172         CFDateFormatterSetFormat(formatter, customFormatCFString);
173         CFRelease(customFormatCFString);
174     }
175
176     CFStringRef string = CFDateFormatterCreateStringWithAbsoluteTime(0, formatter, floor(timeInMilliseconds / msPerSecond) - kCFAbsoluteTimeIntervalSince1970);
177
178     CFRelease(formatter);
179
180     // We truncate the string returned from CFDateFormatter if it's absurdly long (> 200 characters).
181     // That's not great error handling, but it just won't happen so it doesn't matter.
182     UChar buffer[200];
183     const size_t bufferLength = sizeof(buffer) / sizeof(buffer[0]);
184     size_t length = CFStringGetLength(string);
185     ASSERT(length <= bufferLength);
186     if (length > bufferLength)
187         length = bufferLength;
188     CFStringGetCharacters(string, CFRangeMake(0, length), buffer);
189
190     CFRelease(string);
191
192     return jsNontrivialString(exec, UString(buffer, length));
193 }
194
195 #else // !PLATFORM(MAC)
196
197 static JSCell* formatLocaleDate(ExecState* exec, const GregorianDateTime& gdt, LocaleDateTimeFormat format)
198 {
199 #if HAVE(LANGINFO_H)
200     static const nl_item formats[] = { D_T_FMT, D_FMT, T_FMT };
201 #elif PLATFORM(WINCE) && !PLATFORM(QT)
202     // strftime() we are using does not support #
203     static const char* const formatStrings[] = { "%c", "%x", "%X" };
204 #else
205     static const char* const formatStrings[] = { "%#c", "%#x", "%X" };
206 #endif
207  
208     // Offset year if needed
209     struct tm localTM = gdt;
210     int year = gdt.year + 1900;
211     bool yearNeedsOffset = year < 1900 || year > 2038;
212     if (yearNeedsOffset)
213         localTM.tm_year = equivalentYearForDST(year) - 1900;
214  
215 #if HAVE(LANGINFO_H)
216     // We do not allow strftime to generate dates with 2-digits years,
217     // both to avoid ambiguity, and a crash in strncpy, for years that
218     // need offset.
219     char* formatString = strdup(nl_langinfo(formats[format]));
220     char* yPos = strchr(formatString, 'y');
221     if (yPos)
222         *yPos = 'Y';
223 #endif
224
225     // Do the formatting
226     const int bufsize = 128;
227     char timebuffer[bufsize];
228
229 #if HAVE(LANGINFO_H)
230     size_t ret = strftime(timebuffer, bufsize, formatString, &localTM);
231     free(formatString);
232 #else
233     size_t ret = strftime(timebuffer, bufsize, formatStrings[format], &localTM);
234 #endif
235  
236     if (ret == 0)
237         return jsEmptyString(exec);
238  
239     // Copy original into the buffer
240     if (yearNeedsOffset && format != LocaleTime) {
241         static const int yearLen = 5;   // FIXME will be a problem in the year 10,000
242         char yearString[yearLen];
243  
244         snprintf(yearString, yearLen, "%d", localTM.tm_year + 1900);
245         char* yearLocation = strstr(timebuffer, yearString);
246         snprintf(yearString, yearLen, "%d", year);
247  
248         strncpy(yearLocation, yearString, yearLen - 1);
249     }
250  
251     return jsNontrivialString(exec, timebuffer);
252 }
253
254 static JSCell* formatLocaleDate(ExecState* exec, DateInstance* dateObject, double timeInMilliseconds, LocaleDateTimeFormat format, const ArgList&)
255 {
256     GregorianDateTime gregorianDateTime;
257     const bool notUTC = false;
258     dateObject->msToGregorianDateTime(timeInMilliseconds, notUTC, gregorianDateTime);
259     return formatLocaleDate(exec, gregorianDateTime, format);
260 }
261
262 #endif // !PLATFORM(MAC)
263
264 // Converts a list of arguments sent to a Date member function into milliseconds, updating
265 // ms (representing milliseconds) and t (representing the rest of the date structure) appropriately.
266 //
267 // Format of member function: f([hour,] [min,] [sec,] [ms])
268 static bool fillStructuresUsingTimeArgs(ExecState* exec, const ArgList& args, int maxArgs, double* ms, GregorianDateTime* t)
269 {
270     double milliseconds = 0;
271     bool ok = true;
272     int idx = 0;
273     int numArgs = args.size();
274     
275     // JS allows extra trailing arguments -- ignore them
276     if (numArgs > maxArgs)
277         numArgs = maxArgs;
278
279     // hours
280     if (maxArgs >= 4 && idx < numArgs) {
281         t->hour = 0;
282         milliseconds += args.at(idx++).toInt32(exec, ok) * msPerHour;
283     }
284
285     // minutes
286     if (maxArgs >= 3 && idx < numArgs && ok) {
287         t->minute = 0;
288         milliseconds += args.at(idx++).toInt32(exec, ok) * msPerMinute;
289     }
290     
291     // seconds
292     if (maxArgs >= 2 && idx < numArgs && ok) {
293         t->second = 0;
294         milliseconds += args.at(idx++).toInt32(exec, ok) * msPerSecond;
295     }
296     
297     if (!ok)
298         return false;
299         
300     // milliseconds
301     if (idx < numArgs) {
302         double millis = args.at(idx).toNumber(exec);
303         ok = isfinite(millis);
304         milliseconds += millis;
305     } else
306         milliseconds += *ms;
307     
308     *ms = milliseconds;
309     return ok;
310 }
311
312 // Converts a list of arguments sent to a Date member function into years, months, and milliseconds, updating
313 // ms (representing milliseconds) and t (representing the rest of the date structure) appropriately.
314 //
315 // Format of member function: f([years,] [months,] [days])
316 static bool fillStructuresUsingDateArgs(ExecState *exec, const ArgList& args, int maxArgs, double *ms, GregorianDateTime *t)
317 {
318     int idx = 0;
319     bool ok = true;
320     int numArgs = args.size();
321   
322     // JS allows extra trailing arguments -- ignore them
323     if (numArgs > maxArgs)
324         numArgs = maxArgs;
325   
326     // years
327     if (maxArgs >= 3 && idx < numArgs)
328         t->year = args.at(idx++).toInt32(exec, ok) - 1900;
329     
330     // months
331     if (maxArgs >= 2 && idx < numArgs && ok)   
332         t->month = args.at(idx++).toInt32(exec, ok);
333     
334     // days
335     if (idx < numArgs && ok) {   
336         t->monthDay = 0;
337         *ms += args.at(idx).toInt32(exec, ok) * msPerDay;
338     }
339     
340     return ok;
341 }
342
343 const ClassInfo DatePrototype::info = {"Date", &DateInstance::info, 0, ExecState::dateTable};
344
345 /* Source for DatePrototype.lut.h
346 @begin dateTable
347   toString              dateProtoFuncToString                DontEnum|Function       0
348   toISOString           dateProtoFuncToISOString             DontEnum|Function       0
349   toUTCString           dateProtoFuncToUTCString             DontEnum|Function       0
350   toDateString          dateProtoFuncToDateString            DontEnum|Function       0
351   toTimeString          dateProtoFuncToTimeString            DontEnum|Function       0
352   toLocaleString        dateProtoFuncToLocaleString          DontEnum|Function       0
353   toLocaleDateString    dateProtoFuncToLocaleDateString      DontEnum|Function       0
354   toLocaleTimeString    dateProtoFuncToLocaleTimeString      DontEnum|Function       0
355   valueOf               dateProtoFuncGetTime                 DontEnum|Function       0
356   getTime               dateProtoFuncGetTime                 DontEnum|Function       0
357   getFullYear           dateProtoFuncGetFullYear             DontEnum|Function       0
358   getUTCFullYear        dateProtoFuncGetUTCFullYear          DontEnum|Function       0
359   toGMTString           dateProtoFuncToGMTString             DontEnum|Function       0
360   getMonth              dateProtoFuncGetMonth                DontEnum|Function       0
361   getUTCMonth           dateProtoFuncGetUTCMonth             DontEnum|Function       0
362   getDate               dateProtoFuncGetDate                 DontEnum|Function       0
363   getUTCDate            dateProtoFuncGetUTCDate              DontEnum|Function       0
364   getDay                dateProtoFuncGetDay                  DontEnum|Function       0
365   getUTCDay             dateProtoFuncGetUTCDay               DontEnum|Function       0
366   getHours              dateProtoFuncGetHours                DontEnum|Function       0
367   getUTCHours           dateProtoFuncGetUTCHours             DontEnum|Function       0
368   getMinutes            dateProtoFuncGetMinutes              DontEnum|Function       0
369   getUTCMinutes         dateProtoFuncGetUTCMinutes           DontEnum|Function       0
370   getSeconds            dateProtoFuncGetSeconds              DontEnum|Function       0
371   getUTCSeconds         dateProtoFuncGetUTCSeconds           DontEnum|Function       0
372   getMilliseconds       dateProtoFuncGetMilliSeconds         DontEnum|Function       0
373   getUTCMilliseconds    dateProtoFuncGetUTCMilliseconds      DontEnum|Function       0
374   getTimezoneOffset     dateProtoFuncGetTimezoneOffset       DontEnum|Function       0
375   setTime               dateProtoFuncSetTime                 DontEnum|Function       1
376   setMilliseconds       dateProtoFuncSetMilliSeconds         DontEnum|Function       1
377   setUTCMilliseconds    dateProtoFuncSetUTCMilliseconds      DontEnum|Function       1
378   setSeconds            dateProtoFuncSetSeconds              DontEnum|Function       2
379   setUTCSeconds         dateProtoFuncSetUTCSeconds           DontEnum|Function       2
380   setMinutes            dateProtoFuncSetMinutes              DontEnum|Function       3
381   setUTCMinutes         dateProtoFuncSetUTCMinutes           DontEnum|Function       3
382   setHours              dateProtoFuncSetHours                DontEnum|Function       4
383   setUTCHours           dateProtoFuncSetUTCHours             DontEnum|Function       4
384   setDate               dateProtoFuncSetDate                 DontEnum|Function       1
385   setUTCDate            dateProtoFuncSetUTCDate              DontEnum|Function       1
386   setMonth              dateProtoFuncSetMonth                DontEnum|Function       2
387   setUTCMonth           dateProtoFuncSetUTCMonth             DontEnum|Function       2
388   setFullYear           dateProtoFuncSetFullYear             DontEnum|Function       3
389   setUTCFullYear        dateProtoFuncSetUTCFullYear          DontEnum|Function       3
390   setYear               dateProtoFuncSetYear                 DontEnum|Function       1
391   getYear               dateProtoFuncGetYear                 DontEnum|Function       0
392   toJSON                dateProtoFuncToJSON                  DontEnum|Function       0
393 @end
394 */
395
396 // ECMA 15.9.4
397
398 DatePrototype::DatePrototype(ExecState* exec, PassRefPtr<Structure> structure)
399     : DateInstance(structure)
400 {
401     setInternalValue(jsNaN(exec));
402     // The constructor will be added later, after DateConstructor has been built.
403 }
404
405 bool DatePrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
406 {
407     return getStaticFunctionSlot<JSObject>(exec, ExecState::dateTable(exec), this, propertyName, slot);
408 }
409
410
411 bool DatePrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
412 {
413     return getStaticFunctionDescriptor<JSObject>(exec, ExecState::dateTable(exec), this, propertyName, descriptor);
414 }
415
416 // Functions
417
418 JSValue JSC_HOST_CALL dateProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
419 {
420     if (!thisValue.inherits(&DateInstance::info))
421         return throwError(exec, TypeError);
422
423     const bool utc = false;
424
425     DateInstance* thisDateObj = asDateInstance(thisValue); 
426     double milli = thisDateObj->internalNumber();
427     if (isnan(milli))
428         return jsNontrivialString(exec, "Invalid Date");
429
430     GregorianDateTime t;
431     thisDateObj->msToGregorianDateTime(milli, utc, t);
432     return jsNontrivialString(exec, formatDate(t) + " " + formatTime(t, utc));
433 }
434
435 JSValue JSC_HOST_CALL dateProtoFuncToUTCString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
436 {
437     if (!thisValue.inherits(&DateInstance::info))
438         return throwError(exec, TypeError);
439
440     const bool utc = true;
441
442     DateInstance* thisDateObj = asDateInstance(thisValue); 
443     double milli = thisDateObj->internalNumber();
444     if (isnan(milli))
445         return jsNontrivialString(exec, "Invalid Date");
446
447     GregorianDateTime t;
448     thisDateObj->msToGregorianDateTime(milli, utc, t);
449     return jsNontrivialString(exec, formatDateUTCVariant(t) + " " + formatTime(t, utc));
450 }
451
452 JSValue JSC_HOST_CALL dateProtoFuncToISOString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
453 {
454     if (!thisValue.inherits(&DateInstance::info))
455         return throwError(exec, TypeError);
456     
457     const bool utc = true;
458     
459     DateInstance* thisDateObj = asDateInstance(thisValue); 
460     double milli = thisDateObj->internalNumber();
461     if (!isfinite(milli))
462         return jsNontrivialString(exec, "Invalid Date");
463     
464     GregorianDateTime t;
465     thisDateObj->msToGregorianDateTime(milli, utc, t);
466     // Maximum amount of space we need in buffer: 6 (max. digits in year) + 2 * 5 (2 characters each for month, day, hour, minute, second)
467     // 6 for formatting and one for null termination = 23.  We add one extra character to allow us to force null termination.
468     char buffer[24];
469     snprintf(buffer, sizeof(buffer) - 1, "%04d-%02d-%02dT%02d:%02d:%02dZ", 1900 + t.year, t.month + 1, t.monthDay, t.hour, t.minute, t.second);
470     buffer[sizeof(buffer) - 1] = 0;
471     return jsNontrivialString(exec, buffer);
472 }
473
474 JSValue JSC_HOST_CALL dateProtoFuncToDateString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
475 {
476     if (!thisValue.inherits(&DateInstance::info))
477         return throwError(exec, TypeError);
478
479     const bool utc = false;
480
481     DateInstance* thisDateObj = asDateInstance(thisValue); 
482     double milli = thisDateObj->internalNumber();
483     if (isnan(milli))
484         return jsNontrivialString(exec, "Invalid Date");
485
486     GregorianDateTime t;
487     thisDateObj->msToGregorianDateTime(milli, utc, t);
488     return jsNontrivialString(exec, formatDate(t));
489 }
490
491 JSValue JSC_HOST_CALL dateProtoFuncToTimeString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
492 {
493     if (!thisValue.inherits(&DateInstance::info))
494         return throwError(exec, TypeError);
495
496     const bool utc = false;
497
498     DateInstance* thisDateObj = asDateInstance(thisValue); 
499     double milli = thisDateObj->internalNumber();
500     if (isnan(milli))
501         return jsNontrivialString(exec, "Invalid Date");
502
503     GregorianDateTime t;
504     thisDateObj->msToGregorianDateTime(milli, utc, t);
505     return jsNontrivialString(exec, formatTime(t, utc));
506 }
507
508 JSValue JSC_HOST_CALL dateProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
509 {
510     if (!thisValue.inherits(&DateInstance::info))
511         return throwError(exec, TypeError);
512
513     DateInstance* thisDateObj = asDateInstance(thisValue); 
514     double milli = thisDateObj->internalNumber();
515     if (isnan(milli))
516         return jsNontrivialString(exec, "Invalid Date");
517
518     return formatLocaleDate(exec, thisDateObj, milli, LocaleDateAndTime, args);
519 }
520
521 JSValue JSC_HOST_CALL dateProtoFuncToLocaleDateString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
522 {
523     if (!thisValue.inherits(&DateInstance::info))
524         return throwError(exec, TypeError);
525
526     DateInstance* thisDateObj = asDateInstance(thisValue); 
527     double milli = thisDateObj->internalNumber();
528     if (isnan(milli))
529         return jsNontrivialString(exec, "Invalid Date");
530
531     return formatLocaleDate(exec, thisDateObj, milli, LocaleDate, args);
532 }
533
534 JSValue JSC_HOST_CALL dateProtoFuncToLocaleTimeString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
535 {
536     if (!thisValue.inherits(&DateInstance::info))
537         return throwError(exec, TypeError);
538
539     DateInstance* thisDateObj = asDateInstance(thisValue); 
540     double milli = thisDateObj->internalNumber();
541     if (isnan(milli))
542         return jsNontrivialString(exec, "Invalid Date");
543
544     return formatLocaleDate(exec, thisDateObj, milli, LocaleTime, args);
545 }
546
547 JSValue JSC_HOST_CALL dateProtoFuncGetTime(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
548 {
549     if (!thisValue.inherits(&DateInstance::info))
550         return throwError(exec, TypeError);
551
552     DateInstance* thisDateObj = asDateInstance(thisValue); 
553     double milli = thisDateObj->internalNumber();
554     if (isnan(milli))
555         return jsNaN(exec);
556
557     return jsNumber(exec, milli);
558 }
559
560 JSValue JSC_HOST_CALL dateProtoFuncGetFullYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
561 {
562     if (!thisValue.inherits(&DateInstance::info))
563         return throwError(exec, TypeError);
564
565     const bool utc = false;
566
567     DateInstance* thisDateObj = asDateInstance(thisValue); 
568     double milli = thisDateObj->internalNumber();
569     if (isnan(milli))
570         return jsNaN(exec);
571
572     GregorianDateTime t;
573     thisDateObj->msToGregorianDateTime(milli, utc, t);
574     return jsNumber(exec, 1900 + t.year);
575 }
576
577 JSValue JSC_HOST_CALL dateProtoFuncGetUTCFullYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
578 {
579     if (!thisValue.inherits(&DateInstance::info))
580         return throwError(exec, TypeError);
581
582     const bool utc = true;
583
584     DateInstance* thisDateObj = asDateInstance(thisValue); 
585     double milli = thisDateObj->internalNumber();
586     if (isnan(milli))
587         return jsNaN(exec);
588
589     GregorianDateTime t;
590     thisDateObj->msToGregorianDateTime(milli, utc, t);
591     return jsNumber(exec, 1900 + t.year);
592 }
593
594 JSValue JSC_HOST_CALL dateProtoFuncToGMTString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
595 {
596     if (!thisValue.inherits(&DateInstance::info))
597         return throwError(exec, TypeError);
598
599     const bool utc = true;
600
601     DateInstance* thisDateObj = asDateInstance(thisValue); 
602     double milli = thisDateObj->internalNumber();
603     if (isnan(milli))
604         return jsNontrivialString(exec, "Invalid Date");
605
606     GregorianDateTime t;
607     thisDateObj->msToGregorianDateTime(milli, utc, t);
608     return jsNontrivialString(exec, formatDateUTCVariant(t) + " " + formatTime(t, utc));
609 }
610
611 JSValue JSC_HOST_CALL dateProtoFuncGetMonth(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
612 {
613     if (!thisValue.inherits(&DateInstance::info))
614         return throwError(exec, TypeError);
615
616     const bool utc = false;
617
618     DateInstance* thisDateObj = asDateInstance(thisValue); 
619     double milli = thisDateObj->internalNumber();
620     if (isnan(milli))
621         return jsNaN(exec);
622
623     GregorianDateTime t;
624     thisDateObj->msToGregorianDateTime(milli, utc, t);
625     return jsNumber(exec, t.month);
626 }
627
628 JSValue JSC_HOST_CALL dateProtoFuncGetUTCMonth(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
629 {
630     if (!thisValue.inherits(&DateInstance::info))
631         return throwError(exec, TypeError);
632
633     const bool utc = true;
634
635     DateInstance* thisDateObj = asDateInstance(thisValue); 
636     double milli = thisDateObj->internalNumber();
637     if (isnan(milli))
638         return jsNaN(exec);
639
640     GregorianDateTime t;
641     thisDateObj->msToGregorianDateTime(milli, utc, t);
642     return jsNumber(exec, t.month);
643 }
644
645 JSValue JSC_HOST_CALL dateProtoFuncGetDate(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
646 {
647     if (!thisValue.inherits(&DateInstance::info))
648         return throwError(exec, TypeError);
649
650     const bool utc = false;
651
652     DateInstance* thisDateObj = asDateInstance(thisValue); 
653     double milli = thisDateObj->internalNumber();
654     if (isnan(milli))
655         return jsNaN(exec);
656
657     GregorianDateTime t;
658     thisDateObj->msToGregorianDateTime(milli, utc, t);
659     return jsNumber(exec, t.monthDay);
660 }
661
662 JSValue JSC_HOST_CALL dateProtoFuncGetUTCDate(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
663 {
664     if (!thisValue.inherits(&DateInstance::info))
665         return throwError(exec, TypeError);
666
667     const bool utc = true;
668
669     DateInstance* thisDateObj = asDateInstance(thisValue); 
670     double milli = thisDateObj->internalNumber();
671     if (isnan(milli))
672         return jsNaN(exec);
673
674     GregorianDateTime t;
675     thisDateObj->msToGregorianDateTime(milli, utc, t);
676     return jsNumber(exec, t.monthDay);
677 }
678
679 JSValue JSC_HOST_CALL dateProtoFuncGetDay(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
680 {
681     if (!thisValue.inherits(&DateInstance::info))
682         return throwError(exec, TypeError);
683
684     const bool utc = false;
685
686     DateInstance* thisDateObj = asDateInstance(thisValue); 
687     double milli = thisDateObj->internalNumber();
688     if (isnan(milli))
689         return jsNaN(exec);
690
691     GregorianDateTime t;
692     thisDateObj->msToGregorianDateTime(milli, utc, t);
693     return jsNumber(exec, t.weekDay);
694 }
695
696 JSValue JSC_HOST_CALL dateProtoFuncGetUTCDay(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
697 {
698     if (!thisValue.inherits(&DateInstance::info))
699         return throwError(exec, TypeError);
700
701     const bool utc = true;
702
703     DateInstance* thisDateObj = asDateInstance(thisValue); 
704     double milli = thisDateObj->internalNumber();
705     if (isnan(milli))
706         return jsNaN(exec);
707
708     GregorianDateTime t;
709     thisDateObj->msToGregorianDateTime(milli, utc, t);
710     return jsNumber(exec, t.weekDay);
711 }
712
713 JSValue JSC_HOST_CALL dateProtoFuncGetHours(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
714 {
715     if (!thisValue.inherits(&DateInstance::info))
716         return throwError(exec, TypeError);
717
718     const bool utc = false;
719
720     DateInstance* thisDateObj = asDateInstance(thisValue); 
721     double milli = thisDateObj->internalNumber();
722     if (isnan(milli))
723         return jsNaN(exec);
724
725     GregorianDateTime t;
726     thisDateObj->msToGregorianDateTime(milli, utc, t);
727     return jsNumber(exec, t.hour);
728 }
729
730 JSValue JSC_HOST_CALL dateProtoFuncGetUTCHours(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
731 {
732     if (!thisValue.inherits(&DateInstance::info))
733         return throwError(exec, TypeError);
734
735     const bool utc = true;
736
737     DateInstance* thisDateObj = asDateInstance(thisValue); 
738     double milli = thisDateObj->internalNumber();
739     if (isnan(milli))
740         return jsNaN(exec);
741
742     GregorianDateTime t;
743     thisDateObj->msToGregorianDateTime(milli, utc, t);
744     return jsNumber(exec, t.hour);
745 }
746
747 JSValue JSC_HOST_CALL dateProtoFuncGetMinutes(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
748 {
749     if (!thisValue.inherits(&DateInstance::info))
750         return throwError(exec, TypeError);
751
752     const bool utc = false;
753
754     DateInstance* thisDateObj = asDateInstance(thisValue); 
755     double milli = thisDateObj->internalNumber();
756     if (isnan(milli))
757         return jsNaN(exec);
758
759     GregorianDateTime t;
760     thisDateObj->msToGregorianDateTime(milli, utc, t);
761     return jsNumber(exec, t.minute);
762 }
763
764 JSValue JSC_HOST_CALL dateProtoFuncGetUTCMinutes(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
765 {
766     if (!thisValue.inherits(&DateInstance::info))
767         return throwError(exec, TypeError);
768
769     const bool utc = true;
770
771     DateInstance* thisDateObj = asDateInstance(thisValue); 
772     double milli = thisDateObj->internalNumber();
773     if (isnan(milli))
774         return jsNaN(exec);
775
776     GregorianDateTime t;
777     thisDateObj->msToGregorianDateTime(milli, utc, t);
778     return jsNumber(exec, t.minute);
779 }
780
781 JSValue JSC_HOST_CALL dateProtoFuncGetSeconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
782 {
783     if (!thisValue.inherits(&DateInstance::info))
784         return throwError(exec, TypeError);
785
786     const bool utc = false;
787
788     DateInstance* thisDateObj = asDateInstance(thisValue); 
789     double milli = thisDateObj->internalNumber();
790     if (isnan(milli))
791         return jsNaN(exec);
792
793     GregorianDateTime t;
794     thisDateObj->msToGregorianDateTime(milli, utc, t);
795     return jsNumber(exec, t.second);
796 }
797
798 JSValue JSC_HOST_CALL dateProtoFuncGetUTCSeconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
799 {
800     if (!thisValue.inherits(&DateInstance::info))
801         return throwError(exec, TypeError);
802
803     const bool utc = true;
804
805     DateInstance* thisDateObj = asDateInstance(thisValue); 
806     double milli = thisDateObj->internalNumber();
807     if (isnan(milli))
808         return jsNaN(exec);
809
810     GregorianDateTime t;
811     thisDateObj->msToGregorianDateTime(milli, utc, t);
812     return jsNumber(exec, t.second);
813 }
814
815 JSValue JSC_HOST_CALL dateProtoFuncGetMilliSeconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
816 {
817     if (!thisValue.inherits(&DateInstance::info))
818         return throwError(exec, TypeError);
819
820     DateInstance* thisDateObj = asDateInstance(thisValue); 
821     double milli = thisDateObj->internalNumber();
822     if (isnan(milli))
823         return jsNaN(exec);
824
825     double secs = floor(milli / msPerSecond);
826     double ms = milli - secs * msPerSecond;
827     return jsNumber(exec, ms);
828 }
829
830 JSValue JSC_HOST_CALL dateProtoFuncGetUTCMilliseconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
831 {
832     if (!thisValue.inherits(&DateInstance::info))
833         return throwError(exec, TypeError);
834
835     DateInstance* thisDateObj = asDateInstance(thisValue); 
836     double milli = thisDateObj->internalNumber();
837     if (isnan(milli))
838         return jsNaN(exec);
839
840     double secs = floor(milli / msPerSecond);
841     double ms = milli - secs * msPerSecond;
842     return jsNumber(exec, ms);
843 }
844
845 JSValue JSC_HOST_CALL dateProtoFuncGetTimezoneOffset(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
846 {
847     if (!thisValue.inherits(&DateInstance::info))
848         return throwError(exec, TypeError);
849
850     const bool utc = false;
851
852     DateInstance* thisDateObj = asDateInstance(thisValue); 
853     double milli = thisDateObj->internalNumber();
854     if (isnan(milli))
855         return jsNaN(exec);
856
857     GregorianDateTime t;
858     thisDateObj->msToGregorianDateTime(milli, utc, t);
859     return jsNumber(exec, -gmtoffset(t) / minutesPerHour);
860 }
861
862 JSValue JSC_HOST_CALL dateProtoFuncSetTime(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
863 {
864     if (!thisValue.inherits(&DateInstance::info))
865         return throwError(exec, TypeError);
866
867     DateInstance* thisDateObj = asDateInstance(thisValue); 
868
869     double milli = timeClip(args.at(0).toNumber(exec));
870     JSValue result = jsNumber(exec, milli);
871     thisDateObj->setInternalValue(result);
872     return result;
873 }
874
875 static JSValue setNewValueFromTimeArgs(ExecState* exec, JSValue thisValue, const ArgList& args, int numArgsToUse, bool inputIsUTC)
876 {
877     if (!thisValue.inherits(&DateInstance::info))
878         return throwError(exec, TypeError);
879
880     DateInstance* thisDateObj = asDateInstance(thisValue);
881     double milli = thisDateObj->internalNumber();
882     
883     if (args.isEmpty() || isnan(milli)) {
884         JSValue result = jsNaN(exec);
885         thisDateObj->setInternalValue(result);
886         return result;
887     }
888      
889     double secs = floor(milli / msPerSecond);
890     double ms = milli - secs * msPerSecond;
891
892     GregorianDateTime t;
893     thisDateObj->msToGregorianDateTime(milli, inputIsUTC, t);
894
895     if (!fillStructuresUsingTimeArgs(exec, args, numArgsToUse, &ms, &t)) {
896         JSValue result = jsNaN(exec);
897         thisDateObj->setInternalValue(result);
898         return result;
899     } 
900     
901     JSValue result = jsNumber(exec, gregorianDateTimeToMS(t, ms, inputIsUTC));
902     thisDateObj->setInternalValue(result);
903     return result;
904 }
905
906 static JSValue setNewValueFromDateArgs(ExecState* exec, JSValue thisValue, const ArgList& args, int numArgsToUse, bool inputIsUTC)
907 {
908     if (!thisValue.inherits(&DateInstance::info))
909         return throwError(exec, TypeError);
910
911     DateInstance* thisDateObj = asDateInstance(thisValue);
912     if (args.isEmpty()) {
913         JSValue result = jsNaN(exec);
914         thisDateObj->setInternalValue(result);
915         return result;
916     }      
917     
918     double milli = thisDateObj->internalNumber();
919     double ms = 0;
920
921     GregorianDateTime t;
922     if (numArgsToUse == 3 && isnan(milli))
923         // Based on ECMA 262 15.9.5.40 - .41 (set[UTC]FullYear)
924         // the time must be reset to +0 if it is NaN. 
925         thisDateObj->msToGregorianDateTime(0, true, t);
926     else {
927         double secs = floor(milli / msPerSecond);
928         ms = milli - secs * msPerSecond;
929         thisDateObj->msToGregorianDateTime(milli, inputIsUTC, t);
930     }
931     
932     if (!fillStructuresUsingDateArgs(exec, args, numArgsToUse, &ms, &t)) {
933         JSValue result = jsNaN(exec);
934         thisDateObj->setInternalValue(result);
935         return result;
936     } 
937            
938     JSValue result = jsNumber(exec, gregorianDateTimeToMS(t, ms, inputIsUTC));
939     thisDateObj->setInternalValue(result);
940     return result;
941 }
942
943 JSValue JSC_HOST_CALL dateProtoFuncSetMilliSeconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
944 {
945     const bool inputIsUTC = false;
946     return setNewValueFromTimeArgs(exec, thisValue, args, 1, inputIsUTC);
947 }
948
949 JSValue JSC_HOST_CALL dateProtoFuncSetUTCMilliseconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
950 {
951     const bool inputIsUTC = true;
952     return setNewValueFromTimeArgs(exec, thisValue, args, 1, inputIsUTC);
953 }
954
955 JSValue JSC_HOST_CALL dateProtoFuncSetSeconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
956 {
957     const bool inputIsUTC = false;
958     return setNewValueFromTimeArgs(exec, thisValue, args, 2, inputIsUTC);
959 }
960
961 JSValue JSC_HOST_CALL dateProtoFuncSetUTCSeconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
962 {
963     const bool inputIsUTC = true;
964     return setNewValueFromTimeArgs(exec, thisValue, args, 2, inputIsUTC);
965 }
966
967 JSValue JSC_HOST_CALL dateProtoFuncSetMinutes(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
968 {
969     const bool inputIsUTC = false;
970     return setNewValueFromTimeArgs(exec, thisValue, args, 3, inputIsUTC);
971 }
972
973 JSValue JSC_HOST_CALL dateProtoFuncSetUTCMinutes(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
974 {
975     const bool inputIsUTC = true;
976     return setNewValueFromTimeArgs(exec, thisValue, args, 3, inputIsUTC);
977 }
978
979 JSValue JSC_HOST_CALL dateProtoFuncSetHours(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
980 {
981     const bool inputIsUTC = false;
982     return setNewValueFromTimeArgs(exec, thisValue, args, 4, inputIsUTC);
983 }
984
985 JSValue JSC_HOST_CALL dateProtoFuncSetUTCHours(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
986 {
987     const bool inputIsUTC = true;
988     return setNewValueFromTimeArgs(exec, thisValue, args, 4, inputIsUTC);
989 }
990
991 JSValue JSC_HOST_CALL dateProtoFuncSetDate(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
992 {
993     const bool inputIsUTC = false;
994     return setNewValueFromDateArgs(exec, thisValue, args, 1, inputIsUTC);
995 }
996
997 JSValue JSC_HOST_CALL dateProtoFuncSetUTCDate(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
998 {
999     const bool inputIsUTC = true;
1000     return setNewValueFromDateArgs(exec, thisValue, args, 1, inputIsUTC);
1001 }
1002
1003 JSValue JSC_HOST_CALL dateProtoFuncSetMonth(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
1004 {
1005     const bool inputIsUTC = false;
1006     return setNewValueFromDateArgs(exec, thisValue, args, 2, inputIsUTC);
1007 }
1008
1009 JSValue JSC_HOST_CALL dateProtoFuncSetUTCMonth(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
1010 {
1011     const bool inputIsUTC = true;
1012     return setNewValueFromDateArgs(exec, thisValue, args, 2, inputIsUTC);
1013 }
1014
1015 JSValue JSC_HOST_CALL dateProtoFuncSetFullYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
1016 {
1017     const bool inputIsUTC = false;
1018     return setNewValueFromDateArgs(exec, thisValue, args, 3, inputIsUTC);
1019 }
1020
1021 JSValue JSC_HOST_CALL dateProtoFuncSetUTCFullYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
1022 {
1023     const bool inputIsUTC = true;
1024     return setNewValueFromDateArgs(exec, thisValue, args, 3, inputIsUTC);
1025 }
1026
1027 JSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
1028 {
1029     if (!thisValue.inherits(&DateInstance::info))
1030         return throwError(exec, TypeError);
1031
1032     const bool utc = false;
1033
1034     DateInstance* thisDateObj = asDateInstance(thisValue);     
1035     if (args.isEmpty()) { 
1036         JSValue result = jsNaN(exec);
1037         thisDateObj->setInternalValue(result);
1038         return result;
1039     }
1040     
1041     double milli = thisDateObj->internalNumber();
1042     double ms = 0;
1043
1044     GregorianDateTime t;
1045     if (isnan(milli))
1046         // Based on ECMA 262 B.2.5 (setYear)
1047         // the time must be reset to +0 if it is NaN. 
1048         thisDateObj->msToGregorianDateTime(0, true, t);
1049     else {   
1050         double secs = floor(milli / msPerSecond);
1051         ms = milli - secs * msPerSecond;
1052         thisDateObj->msToGregorianDateTime(milli, utc, t);
1053     }
1054     
1055     bool ok = true;
1056     int32_t year = args.at(0).toInt32(exec, ok);
1057     if (!ok) {
1058         JSValue result = jsNaN(exec);
1059         thisDateObj->setInternalValue(result);
1060         return result;
1061     }
1062             
1063     t.year = (year > 99 || year < 0) ? year - 1900 : year;
1064     JSValue result = jsNumber(exec, gregorianDateTimeToMS(t, ms, utc));
1065     thisDateObj->setInternalValue(result);
1066     return result;
1067 }
1068
1069 JSValue JSC_HOST_CALL dateProtoFuncGetYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
1070 {
1071     if (!thisValue.inherits(&DateInstance::info))
1072         return throwError(exec, TypeError);
1073
1074     const bool utc = false;
1075
1076     DateInstance* thisDateObj = asDateInstance(thisValue); 
1077     double milli = thisDateObj->internalNumber();
1078     if (isnan(milli))
1079         return jsNaN(exec);
1080
1081     GregorianDateTime t;
1082     thisDateObj->msToGregorianDateTime(milli, utc, t);
1083
1084     // NOTE: IE returns the full year even in getYear.
1085     return jsNumber(exec, t.year);
1086 }
1087
1088 JSValue JSC_HOST_CALL dateProtoFuncToJSON(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
1089 {
1090     JSObject* object = thisValue.toThisObject(exec);
1091     if (exec->hadException())
1092         return jsNull();
1093     
1094     JSValue toISOValue = object->get(exec, exec->globalData().propertyNames->toISOString);
1095     if (exec->hadException())
1096         return jsNull();
1097
1098     CallData callData;
1099     CallType callType = toISOValue.getCallData(callData);
1100     if (callType == CallTypeNone)
1101         return throwError(exec, TypeError, "toISOString is not a function");
1102
1103     JSValue result = call(exec, asObject(toISOValue), callType, callData, object, exec->emptyList());
1104     if (exec->hadException())
1105         return jsNull();
1106     if (result.isObject())
1107         return throwError(exec, TypeError, "toISOString did not return a primitive value");
1108     return result;
1109 }
1110
1111 } // namespace JSC