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 *
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.
9 *
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.
14 *
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
18 * USA
19 *
20 */
21
22 #include "config.h"
23 #include "DatePrototype.h"
24
25 #include "DateMath.h"
26 #include "JSString.h"
27 #include "ObjectPrototype.h"
28 #include "DateInstance.h"
29 #include <float.h>
30 #include <limits.h>
31 #include <locale.h>
32 #include <math.h>
33 #include <time.h>
34 #include <wtf/Assertions.h>
35 #include <wtf/MathExtras.h>
36 #include <wtf/StringExtras.h>
37 #include <wtf/UnusedParam.h>
38
39 #if HAVE(SYS_PARAM_H)
40 #include <sys/param.h>
41 #endif
42
43 #if HAVE(SYS_TIME_H)
44 #include <sys/time.h>
45 #endif
46
47 #if HAVE(SYS_TIMEB_H)
48 #include <sys/timeb.h>
49 #endif
50
51 #if PLATFORM(MAC)
52 #include <CoreFoundation/CoreFoundation.h>
53 #endif
54
55 using namespace WTF;
56
57 namespace JSC {
58
59 ASSERT_CLASS_FITS_IN_CELL(DatePrototype);
60
61 static JSValuePtr dateProtoFuncGetDate(ExecState*, JSObject*, JSValuePtr, const ArgList&);
62 static JSValuePtr dateProtoFuncGetDay(ExecState*, JSObject*, JSValuePtr, const ArgList&);
63 static JSValuePtr dateProtoFuncGetFullYear(ExecState*, JSObject*, JSValuePtr, const ArgList&);
64 static JSValuePtr dateProtoFuncGetHours(ExecState*, JSObject*, JSValuePtr, const ArgList&);
65 static JSValuePtr dateProtoFuncGetMilliSeconds(ExecState*, JSObject*, JSValuePtr, const ArgList&);
66 static JSValuePtr dateProtoFuncGetMinutes(ExecState*, JSObject*, JSValuePtr, const ArgList&);
67 static JSValuePtr dateProtoFuncGetMonth(ExecState*, JSObject*, JSValuePtr, const ArgList&);
68 static JSValuePtr dateProtoFuncGetSeconds(ExecState*, JSObject*, JSValuePtr, const ArgList&);
69 static JSValuePtr dateProtoFuncGetTime(ExecState*, JSObject*, JSValuePtr, const ArgList&);
70 static JSValuePtr dateProtoFuncGetTimezoneOffset(ExecState*, JSObject*, JSValuePtr, const ArgList&);
71 static JSValuePtr dateProtoFuncGetUTCDate(ExecState*, JSObject*, JSValuePtr, const ArgList&);
72 static JSValuePtr dateProtoFuncGetUTCDay(ExecState*, JSObject*, JSValuePtr, const ArgList&);
73 static JSValuePtr dateProtoFuncGetUTCFullYear(ExecState*, JSObject*, JSValuePtr, const ArgList&);
74 static JSValuePtr dateProtoFuncGetUTCHours(ExecState*, JSObject*, JSValuePtr, const ArgList&);
75 static JSValuePtr dateProtoFuncGetUTCMilliseconds(ExecState*, JSObject*, JSValuePtr, const ArgList&);
76 static JSValuePtr dateProtoFuncGetUTCMinutes(ExecState*, JSObject*, JSValuePtr, const ArgList&);
77 static JSValuePtr dateProtoFuncGetUTCMonth(ExecState*, JSObject*, JSValuePtr, const ArgList&);
78 static JSValuePtr dateProtoFuncGetUTCSeconds(ExecState*, JSObject*, JSValuePtr, const ArgList&);
79 static JSValuePtr dateProtoFuncGetYear(ExecState*, JSObject*, JSValuePtr, const ArgList&);
80 static JSValuePtr dateProtoFuncSetDate(ExecState*, JSObject*, JSValuePtr, const ArgList&);
81 static JSValuePtr dateProtoFuncSetFullYear(ExecState*, JSObject*, JSValuePtr, const ArgList&);
82 static JSValuePtr dateProtoFuncSetHours(ExecState*, JSObject*, JSValuePtr, const ArgList&);
83 static JSValuePtr dateProtoFuncSetMilliSeconds(ExecState*, JSObject*, JSValuePtr, const ArgList&);
84 static JSValuePtr dateProtoFuncSetMinutes(ExecState*, JSObject*, JSValuePtr, const ArgList&);
85 static JSValuePtr dateProtoFuncSetMonth(ExecState*, JSObject*, JSValuePtr, const ArgList&);
86 static JSValuePtr dateProtoFuncSetSeconds(ExecState*, JSObject*, JSValuePtr, const ArgList&);
87 static JSValuePtr dateProtoFuncSetTime(ExecState*, JSObject*, JSValuePtr, const ArgList&);
88 static JSValuePtr dateProtoFuncSetUTCDate(ExecState*, JSObject*, JSValuePtr, const ArgList&);
89 static JSValuePtr dateProtoFuncSetUTCFullYear(ExecState*, JSObject*, JSValuePtr, const ArgList&);
90 static JSValuePtr dateProtoFuncSetUTCHours(ExecState*, JSObject*, JSValuePtr, const ArgList&);
91 static JSValuePtr dateProtoFuncSetUTCMilliseconds(ExecState*, JSObject*, JSValuePtr, const ArgList&);
92 static JSValuePtr dateProtoFuncSetUTCMinutes(ExecState*, JSObject*, JSValuePtr, const ArgList&);
93 static JSValuePtr dateProtoFuncSetUTCMonth(ExecState*, JSObject*, JSValuePtr, const ArgList&);
94 static JSValuePtr dateProtoFuncSetUTCSeconds(ExecState*, JSObject*, JSValuePtr, const ArgList&);
95 static JSValuePtr dateProtoFuncSetYear(ExecState*, JSObject*, JSValuePtr, const ArgList&);
96 static JSValuePtr dateProtoFuncToDateString(ExecState*, JSObject*, JSValuePtr, const ArgList&);
97 static JSValuePtr dateProtoFuncToGMTString(ExecState*, JSObject*, JSValuePtr, const ArgList&);
98 static JSValuePtr dateProtoFuncToLocaleDateString(ExecState*, JSObject*, JSValuePtr, const ArgList&);
99 static JSValuePtr dateProtoFuncToLocaleString(ExecState*, JSObject*, JSValuePtr, const ArgList&);
100 static JSValuePtr dateProtoFuncToLocaleTimeString(ExecState*, JSObject*, JSValuePtr, const ArgList&);
101 static JSValuePtr dateProtoFuncToString(ExecState*, JSObject*, JSValuePtr, const ArgList&);
102 static JSValuePtr dateProtoFuncToTimeString(ExecState*, JSObject*, JSValuePtr, const ArgList&);
103 static JSValuePtr dateProtoFuncToUTCString(ExecState*, JSObject*, JSValuePtr, const ArgList&);
104
105 }
106
107 #include "DatePrototype.lut.h"
108
109 namespace JSC {
110
111 enum LocaleDateTimeFormat { LocaleDateAndTime, LocaleDate, LocaleTime };
112
113 #if PLATFORM(MAC)
114
115 // FIXME: Since this is superior to the strftime-based version, why limit this to PLATFORM(MAC)?
116 // Instead we should consider using this whenever PLATFORM(CF) is true.
117
styleFromArgString(const UString & string,CFDateFormatterStyle defaultStyle)118 static CFDateFormatterStyle styleFromArgString(const UString& string, CFDateFormatterStyle defaultStyle)
119 {
120 if (string == "short")
121 return kCFDateFormatterShortStyle;
122 if (string == "medium")
123 return kCFDateFormatterMediumStyle;
124 if (string == "long")
125 return kCFDateFormatterLongStyle;
126 if (string == "full")
127 return kCFDateFormatterFullStyle;
128 return defaultStyle;
129 }
130
formatLocaleDate(ExecState * exec,DateInstance *,double timeInMilliseconds,LocaleDateTimeFormat format,const ArgList & args)131 static JSCell* formatLocaleDate(ExecState* exec, DateInstance*, double timeInMilliseconds, LocaleDateTimeFormat format, const ArgList& args)
132 {
133 CFDateFormatterStyle dateStyle = (format != LocaleTime ? kCFDateFormatterLongStyle : kCFDateFormatterNoStyle);
134 CFDateFormatterStyle timeStyle = (format != LocaleDate ? kCFDateFormatterLongStyle : kCFDateFormatterNoStyle);
135
136 bool useCustomFormat = false;
137 UString customFormatString;
138
139 UString arg0String = args.at(exec, 0).toString(exec);
140 if (arg0String == "custom" && !args.at(exec, 1).isUndefined()) {
141 useCustomFormat = true;
142 customFormatString = args.at(exec, 1).toString(exec);
143 } else if (format == LocaleDateAndTime && !args.at(exec, 1).isUndefined()) {
144 dateStyle = styleFromArgString(arg0String, dateStyle);
145 timeStyle = styleFromArgString(args.at(exec, 1).toString(exec), timeStyle);
146 } else if (format != LocaleTime && !args.at(exec, 0).isUndefined())
147 dateStyle = styleFromArgString(arg0String, dateStyle);
148 else if (format != LocaleDate && !args.at(exec, 0).isUndefined())
149 timeStyle = styleFromArgString(arg0String, timeStyle);
150
151 CFLocaleRef locale = CFLocaleCopyCurrent();
152 CFDateFormatterRef formatter = CFDateFormatterCreate(0, locale, dateStyle, timeStyle);
153 CFRelease(locale);
154
155 if (useCustomFormat) {
156 CFStringRef customFormatCFString = CFStringCreateWithCharacters(0, customFormatString.data(), customFormatString.size());
157 CFDateFormatterSetFormat(formatter, customFormatCFString);
158 CFRelease(customFormatCFString);
159 }
160
161 CFStringRef string = CFDateFormatterCreateStringWithAbsoluteTime(0, formatter, floor(timeInMilliseconds / msPerSecond) - kCFAbsoluteTimeIntervalSince1970);
162
163 CFRelease(formatter);
164
165 // We truncate the string returned from CFDateFormatter if it's absurdly long (> 200 characters).
166 // That's not great error handling, but it just won't happen so it doesn't matter.
167 UChar buffer[200];
168 const size_t bufferLength = sizeof(buffer) / sizeof(buffer[0]);
169 size_t length = CFStringGetLength(string);
170 ASSERT(length <= bufferLength);
171 if (length > bufferLength)
172 length = bufferLength;
173 CFStringGetCharacters(string, CFRangeMake(0, length), buffer);
174
175 CFRelease(string);
176
177 return jsNontrivialString(exec, UString(buffer, length));
178 }
179
180 #else // !PLATFORM(MAC)
181
formatLocaleDate(ExecState * exec,const GregorianDateTime & gdt,LocaleDateTimeFormat format)182 static JSCell* formatLocaleDate(ExecState* exec, const GregorianDateTime& gdt, LocaleDateTimeFormat format)
183 {
184 static const char* const formatStrings[] = { "%#c", "%#x", "%X" };
185
186 // Offset year if needed
187 struct tm localTM = gdt;
188 int year = gdt.year + 1900;
189 bool yearNeedsOffset = year < 1900 || year > 2038;
190 if (yearNeedsOffset)
191 localTM.tm_year = equivalentYearForDST(year) - 1900;
192
193 // Do the formatting
194 const int bufsize = 128;
195 char timebuffer[bufsize];
196 size_t ret = strftime(timebuffer, bufsize, formatStrings[format], &localTM);
197
198 if (ret == 0)
199 return jsEmptyString(exec);
200
201 // Copy original into the buffer
202 if (yearNeedsOffset && format != LocaleTime) {
203 static const int yearLen = 5; // FIXME will be a problem in the year 10,000
204 char yearString[yearLen];
205
206 snprintf(yearString, yearLen, "%d", localTM.tm_year + 1900);
207 char* yearLocation = strstr(timebuffer, yearString);
208 snprintf(yearString, yearLen, "%d", year);
209
210 strncpy(yearLocation, yearString, yearLen - 1);
211 }
212
213 return jsNontrivialString(exec, timebuffer);
214 }
215
formatLocaleDate(ExecState * exec,DateInstance * dateObject,double timeInMilliseconds,LocaleDateTimeFormat format,const ArgList &)216 static JSCell* formatLocaleDate(ExecState* exec, DateInstance* dateObject, double timeInMilliseconds, LocaleDateTimeFormat format, const ArgList&)
217 {
218 GregorianDateTime gregorianDateTime;
219 const bool notUTC = false;
220 dateObject->msToGregorianDateTime(timeInMilliseconds, notUTC, gregorianDateTime);
221 return formatLocaleDate(exec, gregorianDateTime, format);
222 }
223
224 #endif // !PLATFORM(MAC)
225
226 // Converts a list of arguments sent to a Date member function into milliseconds, updating
227 // ms (representing milliseconds) and t (representing the rest of the date structure) appropriately.
228 //
229 // Format of member function: f([hour,] [min,] [sec,] [ms])
fillStructuresUsingTimeArgs(ExecState * exec,const ArgList & args,int maxArgs,double * ms,GregorianDateTime * t)230 static bool fillStructuresUsingTimeArgs(ExecState* exec, const ArgList& args, int maxArgs, double* ms, GregorianDateTime* t)
231 {
232 double milliseconds = 0;
233 bool ok = true;
234 int idx = 0;
235 int numArgs = args.size();
236
237 // JS allows extra trailing arguments -- ignore them
238 if (numArgs > maxArgs)
239 numArgs = maxArgs;
240
241 // hours
242 if (maxArgs >= 4 && idx < numArgs) {
243 t->hour = 0;
244 milliseconds += args.at(exec, idx++).toInt32(exec, ok) * msPerHour;
245 }
246
247 // minutes
248 if (maxArgs >= 3 && idx < numArgs && ok) {
249 t->minute = 0;
250 milliseconds += args.at(exec, idx++).toInt32(exec, ok) * msPerMinute;
251 }
252
253 // seconds
254 if (maxArgs >= 2 && idx < numArgs && ok) {
255 t->second = 0;
256 milliseconds += args.at(exec, idx++).toInt32(exec, ok) * msPerSecond;
257 }
258
259 if (!ok)
260 return false;
261
262 // milliseconds
263 if (idx < numArgs) {
264 double millis = args.at(exec, idx).toNumber(exec);
265 ok = isfinite(millis);
266 milliseconds += millis;
267 } else
268 milliseconds += *ms;
269
270 *ms = milliseconds;
271 return ok;
272 }
273
274 // Converts a list of arguments sent to a Date member function into years, months, and milliseconds, updating
275 // ms (representing milliseconds) and t (representing the rest of the date structure) appropriately.
276 //
277 // Format of member function: f([years,] [months,] [days])
fillStructuresUsingDateArgs(ExecState * exec,const ArgList & args,int maxArgs,double * ms,GregorianDateTime * t)278 static bool fillStructuresUsingDateArgs(ExecState *exec, const ArgList& args, int maxArgs, double *ms, GregorianDateTime *t)
279 {
280 int idx = 0;
281 bool ok = true;
282 int numArgs = args.size();
283
284 // JS allows extra trailing arguments -- ignore them
285 if (numArgs > maxArgs)
286 numArgs = maxArgs;
287
288 // years
289 if (maxArgs >= 3 && idx < numArgs)
290 t->year = args.at(exec, idx++).toInt32(exec, ok) - 1900;
291
292 // months
293 if (maxArgs >= 2 && idx < numArgs && ok)
294 t->month = args.at(exec, idx++).toInt32(exec, ok);
295
296 // days
297 if (idx < numArgs && ok) {
298 t->monthDay = 0;
299 *ms += args.at(exec, idx).toInt32(exec, ok) * msPerDay;
300 }
301
302 return ok;
303 }
304
305 const ClassInfo DatePrototype::info = {"Date", &DateInstance::info, 0, ExecState::dateTable};
306
307 /* Source for DatePrototype.lut.h
308 @begin dateTable
309 toString dateProtoFuncToString DontEnum|Function 0
310 toUTCString dateProtoFuncToUTCString DontEnum|Function 0
311 toDateString dateProtoFuncToDateString DontEnum|Function 0
312 toTimeString dateProtoFuncToTimeString DontEnum|Function 0
313 toLocaleString dateProtoFuncToLocaleString DontEnum|Function 0
314 toLocaleDateString dateProtoFuncToLocaleDateString DontEnum|Function 0
315 toLocaleTimeString dateProtoFuncToLocaleTimeString DontEnum|Function 0
316 valueOf dateProtoFuncGetTime DontEnum|Function 0
317 getTime dateProtoFuncGetTime DontEnum|Function 0
318 getFullYear dateProtoFuncGetFullYear DontEnum|Function 0
319 getUTCFullYear dateProtoFuncGetUTCFullYear DontEnum|Function 0
320 toGMTString dateProtoFuncToGMTString DontEnum|Function 0
321 getMonth dateProtoFuncGetMonth DontEnum|Function 0
322 getUTCMonth dateProtoFuncGetUTCMonth DontEnum|Function 0
323 getDate dateProtoFuncGetDate DontEnum|Function 0
324 getUTCDate dateProtoFuncGetUTCDate DontEnum|Function 0
325 getDay dateProtoFuncGetDay DontEnum|Function 0
326 getUTCDay dateProtoFuncGetUTCDay DontEnum|Function 0
327 getHours dateProtoFuncGetHours DontEnum|Function 0
328 getUTCHours dateProtoFuncGetUTCHours DontEnum|Function 0
329 getMinutes dateProtoFuncGetMinutes DontEnum|Function 0
330 getUTCMinutes dateProtoFuncGetUTCMinutes DontEnum|Function 0
331 getSeconds dateProtoFuncGetSeconds DontEnum|Function 0
332 getUTCSeconds dateProtoFuncGetUTCSeconds DontEnum|Function 0
333 getMilliseconds dateProtoFuncGetMilliSeconds DontEnum|Function 0
334 getUTCMilliseconds dateProtoFuncGetUTCMilliseconds DontEnum|Function 0
335 getTimezoneOffset dateProtoFuncGetTimezoneOffset DontEnum|Function 0
336 setTime dateProtoFuncSetTime DontEnum|Function 1
337 setMilliseconds dateProtoFuncSetMilliSeconds DontEnum|Function 1
338 setUTCMilliseconds dateProtoFuncSetUTCMilliseconds DontEnum|Function 1
339 setSeconds dateProtoFuncSetSeconds DontEnum|Function 2
340 setUTCSeconds dateProtoFuncSetUTCSeconds DontEnum|Function 2
341 setMinutes dateProtoFuncSetMinutes DontEnum|Function 3
342 setUTCMinutes dateProtoFuncSetUTCMinutes DontEnum|Function 3
343 setHours dateProtoFuncSetHours DontEnum|Function 4
344 setUTCHours dateProtoFuncSetUTCHours DontEnum|Function 4
345 setDate dateProtoFuncSetDate DontEnum|Function 1
346 setUTCDate dateProtoFuncSetUTCDate DontEnum|Function 1
347 setMonth dateProtoFuncSetMonth DontEnum|Function 2
348 setUTCMonth dateProtoFuncSetUTCMonth DontEnum|Function 2
349 setFullYear dateProtoFuncSetFullYear DontEnum|Function 3
350 setUTCFullYear dateProtoFuncSetUTCFullYear DontEnum|Function 3
351 setYear dateProtoFuncSetYear DontEnum|Function 1
352 getYear dateProtoFuncGetYear DontEnum|Function 0
353 @end
354 */
355
356 // ECMA 15.9.4
357
DatePrototype(ExecState * exec,PassRefPtr<Structure> structure)358 DatePrototype::DatePrototype(ExecState* exec, PassRefPtr<Structure> structure)
359 : DateInstance(structure)
360 {
361 setInternalValue(jsNaN(exec));
362 // The constructor will be added later, after DateConstructor has been built.
363 }
364
getOwnPropertySlot(ExecState * exec,const Identifier & propertyName,PropertySlot & slot)365 bool DatePrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
366 {
367 return getStaticFunctionSlot<JSObject>(exec, ExecState::dateTable(exec), this, propertyName, slot);
368 }
369
370 // Functions
371
dateProtoFuncToString(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList &)372 JSValuePtr dateProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
373 {
374 if (!thisValue.isObject(&DateInstance::info))
375 return throwError(exec, TypeError);
376
377 const bool utc = false;
378
379 DateInstance* thisDateObj = asDateInstance(thisValue);
380 double milli = thisDateObj->internalNumber();
381 if (isnan(milli))
382 return jsNontrivialString(exec, "Invalid Date");
383
384 GregorianDateTime t;
385 thisDateObj->msToGregorianDateTime(milli, utc, t);
386 return jsNontrivialString(exec, formatDate(t) + " " + formatTime(t, utc));
387 }
388
dateProtoFuncToUTCString(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList &)389 JSValuePtr dateProtoFuncToUTCString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
390 {
391 if (!thisValue.isObject(&DateInstance::info))
392 return throwError(exec, TypeError);
393
394 const bool utc = true;
395
396 DateInstance* thisDateObj = asDateInstance(thisValue);
397 double milli = thisDateObj->internalNumber();
398 if (isnan(milli))
399 return jsNontrivialString(exec, "Invalid Date");
400
401 GregorianDateTime t;
402 thisDateObj->msToGregorianDateTime(milli, utc, t);
403 return jsNontrivialString(exec, formatDateUTCVariant(t) + " " + formatTime(t, utc));
404 }
405
dateProtoFuncToDateString(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList &)406 JSValuePtr dateProtoFuncToDateString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
407 {
408 if (!thisValue.isObject(&DateInstance::info))
409 return throwError(exec, TypeError);
410
411 const bool utc = false;
412
413 DateInstance* thisDateObj = asDateInstance(thisValue);
414 double milli = thisDateObj->internalNumber();
415 if (isnan(milli))
416 return jsNontrivialString(exec, "Invalid Date");
417
418 GregorianDateTime t;
419 thisDateObj->msToGregorianDateTime(milli, utc, t);
420 return jsNontrivialString(exec, formatDate(t));
421 }
422
dateProtoFuncToTimeString(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList &)423 JSValuePtr dateProtoFuncToTimeString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
424 {
425 if (!thisValue.isObject(&DateInstance::info))
426 return throwError(exec, TypeError);
427
428 const bool utc = false;
429
430 DateInstance* thisDateObj = asDateInstance(thisValue);
431 double milli = thisDateObj->internalNumber();
432 if (isnan(milli))
433 return jsNontrivialString(exec, "Invalid Date");
434
435 GregorianDateTime t;
436 thisDateObj->msToGregorianDateTime(milli, utc, t);
437 return jsNontrivialString(exec, formatTime(t, utc));
438 }
439
dateProtoFuncToLocaleString(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList & args)440 JSValuePtr dateProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
441 {
442 if (!thisValue.isObject(&DateInstance::info))
443 return throwError(exec, TypeError);
444
445 DateInstance* thisDateObj = asDateInstance(thisValue);
446 double milli = thisDateObj->internalNumber();
447 if (isnan(milli))
448 return jsNontrivialString(exec, "Invalid Date");
449
450 return formatLocaleDate(exec, thisDateObj, milli, LocaleDateAndTime, args);
451 }
452
dateProtoFuncToLocaleDateString(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList & args)453 JSValuePtr dateProtoFuncToLocaleDateString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
454 {
455 if (!thisValue.isObject(&DateInstance::info))
456 return throwError(exec, TypeError);
457
458 DateInstance* thisDateObj = asDateInstance(thisValue);
459 double milli = thisDateObj->internalNumber();
460 if (isnan(milli))
461 return jsNontrivialString(exec, "Invalid Date");
462
463 return formatLocaleDate(exec, thisDateObj, milli, LocaleDate, args);
464 }
465
dateProtoFuncToLocaleTimeString(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList & args)466 JSValuePtr dateProtoFuncToLocaleTimeString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
467 {
468 if (!thisValue.isObject(&DateInstance::info))
469 return throwError(exec, TypeError);
470
471 DateInstance* thisDateObj = asDateInstance(thisValue);
472 double milli = thisDateObj->internalNumber();
473 if (isnan(milli))
474 return jsNontrivialString(exec, "Invalid Date");
475
476 return formatLocaleDate(exec, thisDateObj, milli, LocaleTime, args);
477 }
478
dateProtoFuncGetTime(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList &)479 JSValuePtr dateProtoFuncGetTime(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
480 {
481 if (!thisValue.isObject(&DateInstance::info))
482 return throwError(exec, TypeError);
483
484 DateInstance* thisDateObj = asDateInstance(thisValue);
485 double milli = thisDateObj->internalNumber();
486 if (isnan(milli))
487 return jsNaN(exec);
488
489 return jsNumber(exec, milli);
490 }
491
dateProtoFuncGetFullYear(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList &)492 JSValuePtr dateProtoFuncGetFullYear(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
493 {
494 if (!thisValue.isObject(&DateInstance::info))
495 return throwError(exec, TypeError);
496
497 const bool utc = false;
498
499 DateInstance* thisDateObj = asDateInstance(thisValue);
500 double milli = thisDateObj->internalNumber();
501 if (isnan(milli))
502 return jsNaN(exec);
503
504 GregorianDateTime t;
505 thisDateObj->msToGregorianDateTime(milli, utc, t);
506 return jsNumber(exec, 1900 + t.year);
507 }
508
dateProtoFuncGetUTCFullYear(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList &)509 JSValuePtr dateProtoFuncGetUTCFullYear(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
510 {
511 if (!thisValue.isObject(&DateInstance::info))
512 return throwError(exec, TypeError);
513
514 const bool utc = true;
515
516 DateInstance* thisDateObj = asDateInstance(thisValue);
517 double milli = thisDateObj->internalNumber();
518 if (isnan(milli))
519 return jsNaN(exec);
520
521 GregorianDateTime t;
522 thisDateObj->msToGregorianDateTime(milli, utc, t);
523 return jsNumber(exec, 1900 + t.year);
524 }
525
dateProtoFuncToGMTString(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList &)526 JSValuePtr dateProtoFuncToGMTString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
527 {
528 if (!thisValue.isObject(&DateInstance::info))
529 return throwError(exec, TypeError);
530
531 const bool utc = true;
532
533 DateInstance* thisDateObj = asDateInstance(thisValue);
534 double milli = thisDateObj->internalNumber();
535 if (isnan(milli))
536 return jsNontrivialString(exec, "Invalid Date");
537
538 GregorianDateTime t;
539 thisDateObj->msToGregorianDateTime(milli, utc, t);
540 return jsNontrivialString(exec, formatDateUTCVariant(t) + " " + formatTime(t, utc));
541 }
542
dateProtoFuncGetMonth(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList &)543 JSValuePtr dateProtoFuncGetMonth(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
544 {
545 if (!thisValue.isObject(&DateInstance::info))
546 return throwError(exec, TypeError);
547
548 const bool utc = false;
549
550 DateInstance* thisDateObj = asDateInstance(thisValue);
551 double milli = thisDateObj->internalNumber();
552 if (isnan(milli))
553 return jsNaN(exec);
554
555 GregorianDateTime t;
556 thisDateObj->msToGregorianDateTime(milli, utc, t);
557 return jsNumber(exec, t.month);
558 }
559
dateProtoFuncGetUTCMonth(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList &)560 JSValuePtr dateProtoFuncGetUTCMonth(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
561 {
562 if (!thisValue.isObject(&DateInstance::info))
563 return throwError(exec, TypeError);
564
565 const bool utc = true;
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, t.month);
575 }
576
dateProtoFuncGetDate(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList &)577 JSValuePtr dateProtoFuncGetDate(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
578 {
579 if (!thisValue.isObject(&DateInstance::info))
580 return throwError(exec, TypeError);
581
582 const bool utc = false;
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, t.monthDay);
592 }
593
dateProtoFuncGetUTCDate(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList &)594 JSValuePtr dateProtoFuncGetUTCDate(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
595 {
596 if (!thisValue.isObject(&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 jsNaN(exec);
605
606 GregorianDateTime t;
607 thisDateObj->msToGregorianDateTime(milli, utc, t);
608 return jsNumber(exec, t.monthDay);
609 }
610
dateProtoFuncGetDay(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList &)611 JSValuePtr dateProtoFuncGetDay(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
612 {
613 if (!thisValue.isObject(&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.weekDay);
626 }
627
dateProtoFuncGetUTCDay(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList &)628 JSValuePtr dateProtoFuncGetUTCDay(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
629 {
630 if (!thisValue.isObject(&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.weekDay);
643 }
644
dateProtoFuncGetHours(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList &)645 JSValuePtr dateProtoFuncGetHours(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
646 {
647 if (!thisValue.isObject(&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.hour);
660 }
661
dateProtoFuncGetUTCHours(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList &)662 JSValuePtr dateProtoFuncGetUTCHours(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
663 {
664 if (!thisValue.isObject(&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.hour);
677 }
678
dateProtoFuncGetMinutes(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList &)679 JSValuePtr dateProtoFuncGetMinutes(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
680 {
681 if (!thisValue.isObject(&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.minute);
694 }
695
dateProtoFuncGetUTCMinutes(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList &)696 JSValuePtr dateProtoFuncGetUTCMinutes(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
697 {
698 if (!thisValue.isObject(&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.minute);
711 }
712
dateProtoFuncGetSeconds(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList &)713 JSValuePtr dateProtoFuncGetSeconds(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
714 {
715 if (!thisValue.isObject(&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.second);
728 }
729
dateProtoFuncGetUTCSeconds(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList &)730 JSValuePtr dateProtoFuncGetUTCSeconds(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
731 {
732 if (!thisValue.isObject(&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.second);
745 }
746
dateProtoFuncGetMilliSeconds(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList &)747 JSValuePtr dateProtoFuncGetMilliSeconds(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
748 {
749 if (!thisValue.isObject(&DateInstance::info))
750 return throwError(exec, TypeError);
751
752 DateInstance* thisDateObj = asDateInstance(thisValue);
753 double milli = thisDateObj->internalNumber();
754 if (isnan(milli))
755 return jsNaN(exec);
756
757 double secs = floor(milli / msPerSecond);
758 double ms = milli - secs * msPerSecond;
759 return jsNumber(exec, ms);
760 }
761
dateProtoFuncGetUTCMilliseconds(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList &)762 JSValuePtr dateProtoFuncGetUTCMilliseconds(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
763 {
764 if (!thisValue.isObject(&DateInstance::info))
765 return throwError(exec, TypeError);
766
767 DateInstance* thisDateObj = asDateInstance(thisValue);
768 double milli = thisDateObj->internalNumber();
769 if (isnan(milli))
770 return jsNaN(exec);
771
772 double secs = floor(milli / msPerSecond);
773 double ms = milli - secs * msPerSecond;
774 return jsNumber(exec, ms);
775 }
776
dateProtoFuncGetTimezoneOffset(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList &)777 JSValuePtr dateProtoFuncGetTimezoneOffset(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
778 {
779 if (!thisValue.isObject(&DateInstance::info))
780 return throwError(exec, TypeError);
781
782 const bool utc = false;
783
784 DateInstance* thisDateObj = asDateInstance(thisValue);
785 double milli = thisDateObj->internalNumber();
786 if (isnan(milli))
787 return jsNaN(exec);
788
789 GregorianDateTime t;
790 thisDateObj->msToGregorianDateTime(milli, utc, t);
791 return jsNumber(exec, -gmtoffset(t) / minutesPerHour);
792 }
793
dateProtoFuncSetTime(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList & args)794 JSValuePtr dateProtoFuncSetTime(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
795 {
796 if (!thisValue.isObject(&DateInstance::info))
797 return throwError(exec, TypeError);
798
799 DateInstance* thisDateObj = asDateInstance(thisValue);
800
801 double milli = timeClip(args.at(exec, 0).toNumber(exec));
802 JSValuePtr result = jsNumber(exec, milli);
803 thisDateObj->setInternalValue(result);
804 return result;
805 }
806
setNewValueFromTimeArgs(ExecState * exec,JSValuePtr thisValue,const ArgList & args,int numArgsToUse,bool inputIsUTC)807 static JSValuePtr setNewValueFromTimeArgs(ExecState* exec, JSValuePtr thisValue, const ArgList& args, int numArgsToUse, bool inputIsUTC)
808 {
809 if (!thisValue.isObject(&DateInstance::info))
810 return throwError(exec, TypeError);
811
812 DateInstance* thisDateObj = asDateInstance(thisValue);
813 double milli = thisDateObj->internalNumber();
814
815 if (args.isEmpty() || isnan(milli)) {
816 JSValuePtr result = jsNaN(exec);
817 thisDateObj->setInternalValue(result);
818 return result;
819 }
820
821 double secs = floor(milli / msPerSecond);
822 double ms = milli - secs * msPerSecond;
823
824 GregorianDateTime t;
825 thisDateObj->msToGregorianDateTime(milli, inputIsUTC, t);
826
827 if (!fillStructuresUsingTimeArgs(exec, args, numArgsToUse, &ms, &t)) {
828 JSValuePtr result = jsNaN(exec);
829 thisDateObj->setInternalValue(result);
830 return result;
831 }
832
833 JSValuePtr result = jsNumber(exec, gregorianDateTimeToMS(t, ms, inputIsUTC));
834 thisDateObj->setInternalValue(result);
835 return result;
836 }
837
setNewValueFromDateArgs(ExecState * exec,JSValuePtr thisValue,const ArgList & args,int numArgsToUse,bool inputIsUTC)838 static JSValuePtr setNewValueFromDateArgs(ExecState* exec, JSValuePtr thisValue, const ArgList& args, int numArgsToUse, bool inputIsUTC)
839 {
840 if (!thisValue.isObject(&DateInstance::info))
841 return throwError(exec, TypeError);
842
843 DateInstance* thisDateObj = asDateInstance(thisValue);
844 if (args.isEmpty()) {
845 JSValuePtr result = jsNaN(exec);
846 thisDateObj->setInternalValue(result);
847 return result;
848 }
849
850 double milli = thisDateObj->internalNumber();
851 double ms = 0;
852
853 GregorianDateTime t;
854 if (numArgsToUse == 3 && isnan(milli))
855 // Based on ECMA 262 15.9.5.40 - .41 (set[UTC]FullYear)
856 // the time must be reset to +0 if it is NaN.
857 thisDateObj->msToGregorianDateTime(0, true, t);
858 else {
859 double secs = floor(milli / msPerSecond);
860 ms = milli - secs * msPerSecond;
861 thisDateObj->msToGregorianDateTime(milli, inputIsUTC, t);
862 }
863
864 if (!fillStructuresUsingDateArgs(exec, args, numArgsToUse, &ms, &t)) {
865 JSValuePtr result = jsNaN(exec);
866 thisDateObj->setInternalValue(result);
867 return result;
868 }
869
870 JSValuePtr result = jsNumber(exec, gregorianDateTimeToMS(t, ms, inputIsUTC));
871 thisDateObj->setInternalValue(result);
872 return result;
873 }
874
dateProtoFuncSetMilliSeconds(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList & args)875 JSValuePtr dateProtoFuncSetMilliSeconds(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
876 {
877 const bool inputIsUTC = false;
878 return setNewValueFromTimeArgs(exec, thisValue, args, 1, inputIsUTC);
879 }
880
dateProtoFuncSetUTCMilliseconds(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList & args)881 JSValuePtr dateProtoFuncSetUTCMilliseconds(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
882 {
883 const bool inputIsUTC = true;
884 return setNewValueFromTimeArgs(exec, thisValue, args, 1, inputIsUTC);
885 }
886
dateProtoFuncSetSeconds(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList & args)887 JSValuePtr dateProtoFuncSetSeconds(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
888 {
889 const bool inputIsUTC = false;
890 return setNewValueFromTimeArgs(exec, thisValue, args, 2, inputIsUTC);
891 }
892
dateProtoFuncSetUTCSeconds(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList & args)893 JSValuePtr dateProtoFuncSetUTCSeconds(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
894 {
895 const bool inputIsUTC = true;
896 return setNewValueFromTimeArgs(exec, thisValue, args, 2, inputIsUTC);
897 }
898
dateProtoFuncSetMinutes(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList & args)899 JSValuePtr dateProtoFuncSetMinutes(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
900 {
901 const bool inputIsUTC = false;
902 return setNewValueFromTimeArgs(exec, thisValue, args, 3, inputIsUTC);
903 }
904
dateProtoFuncSetUTCMinutes(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList & args)905 JSValuePtr dateProtoFuncSetUTCMinutes(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
906 {
907 const bool inputIsUTC = true;
908 return setNewValueFromTimeArgs(exec, thisValue, args, 3, inputIsUTC);
909 }
910
dateProtoFuncSetHours(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList & args)911 JSValuePtr dateProtoFuncSetHours(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
912 {
913 const bool inputIsUTC = false;
914 return setNewValueFromTimeArgs(exec, thisValue, args, 4, inputIsUTC);
915 }
916
dateProtoFuncSetUTCHours(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList & args)917 JSValuePtr dateProtoFuncSetUTCHours(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
918 {
919 const bool inputIsUTC = true;
920 return setNewValueFromTimeArgs(exec, thisValue, args, 4, inputIsUTC);
921 }
922
dateProtoFuncSetDate(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList & args)923 JSValuePtr dateProtoFuncSetDate(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
924 {
925 const bool inputIsUTC = false;
926 return setNewValueFromDateArgs(exec, thisValue, args, 1, inputIsUTC);
927 }
928
dateProtoFuncSetUTCDate(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList & args)929 JSValuePtr dateProtoFuncSetUTCDate(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
930 {
931 const bool inputIsUTC = true;
932 return setNewValueFromDateArgs(exec, thisValue, args, 1, inputIsUTC);
933 }
934
dateProtoFuncSetMonth(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList & args)935 JSValuePtr dateProtoFuncSetMonth(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
936 {
937 const bool inputIsUTC = false;
938 return setNewValueFromDateArgs(exec, thisValue, args, 2, inputIsUTC);
939 }
940
dateProtoFuncSetUTCMonth(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList & args)941 JSValuePtr dateProtoFuncSetUTCMonth(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
942 {
943 const bool inputIsUTC = true;
944 return setNewValueFromDateArgs(exec, thisValue, args, 2, inputIsUTC);
945 }
946
dateProtoFuncSetFullYear(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList & args)947 JSValuePtr dateProtoFuncSetFullYear(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
948 {
949 const bool inputIsUTC = false;
950 return setNewValueFromDateArgs(exec, thisValue, args, 3, inputIsUTC);
951 }
952
dateProtoFuncSetUTCFullYear(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList & args)953 JSValuePtr dateProtoFuncSetUTCFullYear(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
954 {
955 const bool inputIsUTC = true;
956 return setNewValueFromDateArgs(exec, thisValue, args, 3, inputIsUTC);
957 }
958
dateProtoFuncSetYear(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList & args)959 JSValuePtr dateProtoFuncSetYear(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
960 {
961 if (!thisValue.isObject(&DateInstance::info))
962 return throwError(exec, TypeError);
963
964 const bool utc = false;
965
966 DateInstance* thisDateObj = asDateInstance(thisValue);
967 if (args.isEmpty()) {
968 JSValuePtr result = jsNaN(exec);
969 thisDateObj->setInternalValue(result);
970 return result;
971 }
972
973 double milli = thisDateObj->internalNumber();
974 double ms = 0;
975
976 GregorianDateTime t;
977 if (isnan(milli))
978 // Based on ECMA 262 B.2.5 (setYear)
979 // the time must be reset to +0 if it is NaN.
980 thisDateObj->msToGregorianDateTime(0, true, t);
981 else {
982 double secs = floor(milli / msPerSecond);
983 ms = milli - secs * msPerSecond;
984 thisDateObj->msToGregorianDateTime(milli, utc, t);
985 }
986
987 bool ok = true;
988 int32_t year = args.at(exec, 0).toInt32(exec, ok);
989 if (!ok) {
990 JSValuePtr result = jsNaN(exec);
991 thisDateObj->setInternalValue(result);
992 return result;
993 }
994
995 t.year = (year > 99 || year < 0) ? year - 1900 : year;
996 JSValuePtr result = jsNumber(exec, gregorianDateTimeToMS(t, ms, utc));
997 thisDateObj->setInternalValue(result);
998 return result;
999 }
1000
dateProtoFuncGetYear(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList &)1001 JSValuePtr dateProtoFuncGetYear(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
1002 {
1003 if (!thisValue.isObject(&DateInstance::info))
1004 return throwError(exec, TypeError);
1005
1006 const bool utc = false;
1007
1008 DateInstance* thisDateObj = asDateInstance(thisValue);
1009 double milli = thisDateObj->internalNumber();
1010 if (isnan(milli))
1011 return jsNaN(exec);
1012
1013 GregorianDateTime t;
1014 thisDateObj->msToGregorianDateTime(milli, utc, t);
1015
1016 // NOTE: IE returns the full year even in getYear.
1017 return jsNumber(exec, t.year);
1018 }
1019
1020 } // namespace JSC
1021