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.
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.
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.
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
24 #include "DatePrototype.h"
26 #include "DateConversion.h"
29 #include "ObjectPrototype.h"
30 #include "DateInstance.h"
32 #if !PLATFORM(MAC) && HAVE(LANGINFO_H)
40 #include <wtf/Assertions.h>
41 #include <wtf/DateMath.h>
42 #include <wtf/MathExtras.h>
43 #include <wtf/StringExtras.h>
44 #include <wtf/UnusedParam.h>
47 #include <sys/param.h>
55 #include <sys/timeb.h>
59 #include <CoreFoundation/CoreFoundation.h>
62 #if PLATFORM(WINCE) && !PLATFORM(QT)
63 extern "C" size_t strftime(char * const s
, const size_t maxsize
, const char * const format
, const struct tm
* const t
); //provided by libce
70 ASSERT_CLASS_FITS_IN_CELL(DatePrototype
);
72 static JSValue JSC_HOST_CALL
dateProtoFuncGetDate(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
73 static JSValue JSC_HOST_CALL
dateProtoFuncGetDay(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
74 static JSValue JSC_HOST_CALL
dateProtoFuncGetFullYear(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
75 static JSValue JSC_HOST_CALL
dateProtoFuncGetHours(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
76 static JSValue JSC_HOST_CALL
dateProtoFuncGetMilliSeconds(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
77 static JSValue JSC_HOST_CALL
dateProtoFuncGetMinutes(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
78 static JSValue JSC_HOST_CALL
dateProtoFuncGetMonth(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
79 static JSValue JSC_HOST_CALL
dateProtoFuncGetSeconds(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
80 static JSValue JSC_HOST_CALL
dateProtoFuncGetTime(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
81 static JSValue JSC_HOST_CALL
dateProtoFuncGetTimezoneOffset(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
82 static JSValue JSC_HOST_CALL
dateProtoFuncGetUTCDate(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
83 static JSValue JSC_HOST_CALL
dateProtoFuncGetUTCDay(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
84 static JSValue JSC_HOST_CALL
dateProtoFuncGetUTCFullYear(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
85 static JSValue JSC_HOST_CALL
dateProtoFuncGetUTCHours(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
86 static JSValue JSC_HOST_CALL
dateProtoFuncGetUTCMilliseconds(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
87 static JSValue JSC_HOST_CALL
dateProtoFuncGetUTCMinutes(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
88 static JSValue JSC_HOST_CALL
dateProtoFuncGetUTCMonth(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
89 static JSValue JSC_HOST_CALL
dateProtoFuncGetUTCSeconds(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
90 static JSValue JSC_HOST_CALL
dateProtoFuncGetYear(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
91 static JSValue JSC_HOST_CALL
dateProtoFuncSetDate(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
92 static JSValue JSC_HOST_CALL
dateProtoFuncSetFullYear(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
93 static JSValue JSC_HOST_CALL
dateProtoFuncSetHours(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
94 static JSValue JSC_HOST_CALL
dateProtoFuncSetMilliSeconds(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
95 static JSValue JSC_HOST_CALL
dateProtoFuncSetMinutes(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
96 static JSValue JSC_HOST_CALL
dateProtoFuncSetMonth(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
97 static JSValue JSC_HOST_CALL
dateProtoFuncSetSeconds(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
98 static JSValue JSC_HOST_CALL
dateProtoFuncSetTime(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
99 static JSValue JSC_HOST_CALL
dateProtoFuncSetUTCDate(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
100 static JSValue JSC_HOST_CALL
dateProtoFuncSetUTCFullYear(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
101 static JSValue JSC_HOST_CALL
dateProtoFuncSetUTCHours(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
102 static JSValue JSC_HOST_CALL
dateProtoFuncSetUTCMilliseconds(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
103 static JSValue JSC_HOST_CALL
dateProtoFuncSetUTCMinutes(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
104 static JSValue JSC_HOST_CALL
dateProtoFuncSetUTCMonth(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
105 static JSValue JSC_HOST_CALL
dateProtoFuncSetUTCSeconds(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
106 static JSValue JSC_HOST_CALL
dateProtoFuncSetYear(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
107 static JSValue JSC_HOST_CALL
dateProtoFuncToDateString(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
108 static JSValue JSC_HOST_CALL
dateProtoFuncToGMTString(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
109 static JSValue JSC_HOST_CALL
dateProtoFuncToLocaleDateString(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
110 static JSValue JSC_HOST_CALL
dateProtoFuncToLocaleString(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
111 static JSValue JSC_HOST_CALL
dateProtoFuncToLocaleTimeString(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
112 static JSValue JSC_HOST_CALL
dateProtoFuncToString(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
113 static JSValue JSC_HOST_CALL
dateProtoFuncToTimeString(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
114 static JSValue JSC_HOST_CALL
dateProtoFuncToUTCString(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
115 static JSValue JSC_HOST_CALL
dateProtoFuncToISOString(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
117 static JSValue JSC_HOST_CALL
dateProtoFuncToJSON(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
121 #include "DatePrototype.lut.h"
125 enum LocaleDateTimeFormat
{ LocaleDateAndTime
, LocaleDate
, LocaleTime
};
129 // FIXME: Since this is superior to the strftime-based version, why limit this to PLATFORM(MAC)?
130 // Instead we should consider using this whenever PLATFORM(CF) is true.
132 static CFDateFormatterStyle
styleFromArgString(const UString
& string
, CFDateFormatterStyle defaultStyle
)
134 if (string
== "short")
135 return kCFDateFormatterShortStyle
;
136 if (string
== "medium")
137 return kCFDateFormatterMediumStyle
;
138 if (string
== "long")
139 return kCFDateFormatterLongStyle
;
140 if (string
== "full")
141 return kCFDateFormatterFullStyle
;
145 static JSCell
* formatLocaleDate(ExecState
* exec
, DateInstance
*, double timeInMilliseconds
, LocaleDateTimeFormat format
, const ArgList
& args
)
147 CFDateFormatterStyle dateStyle
= (format
!= LocaleTime
? kCFDateFormatterLongStyle
: kCFDateFormatterNoStyle
);
148 CFDateFormatterStyle timeStyle
= (format
!= LocaleDate
? kCFDateFormatterLongStyle
: kCFDateFormatterNoStyle
);
150 bool useCustomFormat
= false;
151 UString customFormatString
;
153 UString arg0String
= args
.at(0).toString(exec
);
154 if (arg0String
== "custom" && !args
.at(1).isUndefined()) {
155 useCustomFormat
= true;
156 customFormatString
= args
.at(1).toString(exec
);
157 } else if (format
== LocaleDateAndTime
&& !args
.at(1).isUndefined()) {
158 dateStyle
= styleFromArgString(arg0String
, dateStyle
);
159 timeStyle
= styleFromArgString(args
.at(1).toString(exec
), timeStyle
);
160 } else if (format
!= LocaleTime
&& !args
.at(0).isUndefined())
161 dateStyle
= styleFromArgString(arg0String
, dateStyle
);
162 else if (format
!= LocaleDate
&& !args
.at(0).isUndefined())
163 timeStyle
= styleFromArgString(arg0String
, timeStyle
);
165 CFLocaleRef locale
= CFLocaleCopyCurrent();
166 CFDateFormatterRef formatter
= CFDateFormatterCreate(0, locale
, dateStyle
, timeStyle
);
169 if (useCustomFormat
) {
170 CFStringRef customFormatCFString
= CFStringCreateWithCharacters(0, customFormatString
.data(), customFormatString
.size());
171 CFDateFormatterSetFormat(formatter
, customFormatCFString
);
172 CFRelease(customFormatCFString
);
175 CFStringRef string
= CFDateFormatterCreateStringWithAbsoluteTime(0, formatter
, floor(timeInMilliseconds
/ msPerSecond
) - kCFAbsoluteTimeIntervalSince1970
);
177 CFRelease(formatter
);
179 // We truncate the string returned from CFDateFormatter if it's absurdly long (> 200 characters).
180 // That's not great error handling, but it just won't happen so it doesn't matter.
182 const size_t bufferLength
= sizeof(buffer
) / sizeof(buffer
[0]);
183 size_t length
= CFStringGetLength(string
);
184 ASSERT(length
<= bufferLength
);
185 if (length
> bufferLength
)
186 length
= bufferLength
;
187 CFStringGetCharacters(string
, CFRangeMake(0, length
), buffer
);
191 return jsNontrivialString(exec
, UString(buffer
, length
));
194 #else // !PLATFORM(MAC)
196 static JSCell
* formatLocaleDate(ExecState
* exec
, const GregorianDateTime
& gdt
, LocaleDateTimeFormat format
)
199 static const nl_item formats
[] = { D_T_FMT
, D_FMT
, T_FMT
};
200 #elif (PLATFORM(WINCE) && !PLATFORM(QT)) || PLATFORM(SYMBIAN)
201 // strftime() does not support '#' on WinCE or Symbian
202 static const char* const formatStrings
[] = { "%c", "%x", "%X" };
204 static const char* const formatStrings
[] = { "%#c", "%#x", "%X" };
207 // Offset year if needed
208 struct tm localTM
= gdt
;
209 int year
= gdt
.year
+ 1900;
210 bool yearNeedsOffset
= year
< 1900 || year
> 2038;
212 localTM
.tm_year
= equivalentYearForDST(year
) - 1900;
215 // We do not allow strftime to generate dates with 2-digits years,
216 // both to avoid ambiguity, and a crash in strncpy, for years that
218 char* formatString
= strdup(nl_langinfo(formats
[format
]));
219 char* yPos
= strchr(formatString
, 'y');
225 const int bufsize
= 128;
226 char timebuffer
[bufsize
];
229 size_t ret
= strftime(timebuffer
, bufsize
, formatString
, &localTM
);
232 size_t ret
= strftime(timebuffer
, bufsize
, formatStrings
[format
], &localTM
);
236 return jsEmptyString(exec
);
238 // Copy original into the buffer
239 if (yearNeedsOffset
&& format
!= LocaleTime
) {
240 static const int yearLen
= 5; // FIXME will be a problem in the year 10,000
241 char yearString
[yearLen
];
243 snprintf(yearString
, yearLen
, "%d", localTM
.tm_year
+ 1900);
244 char* yearLocation
= strstr(timebuffer
, yearString
);
245 snprintf(yearString
, yearLen
, "%d", year
);
247 strncpy(yearLocation
, yearString
, yearLen
- 1);
250 return jsNontrivialString(exec
, timebuffer
);
253 static JSCell
* formatLocaleDate(ExecState
* exec
, DateInstance
* dateObject
, double, LocaleDateTimeFormat format
, const ArgList
&)
255 const GregorianDateTime
* gregorianDateTime
= dateObject
->gregorianDateTime(exec
);
256 if (!gregorianDateTime
)
257 return jsNontrivialString(exec
, "Invalid Date");
258 return formatLocaleDate(exec
, *gregorianDateTime
, format
);
261 #endif // !PLATFORM(MAC)
263 // Converts a list of arguments sent to a Date member function into milliseconds, updating
264 // ms (representing milliseconds) and t (representing the rest of the date structure) appropriately.
266 // Format of member function: f([hour,] [min,] [sec,] [ms])
267 static bool fillStructuresUsingTimeArgs(ExecState
* exec
, const ArgList
& args
, int maxArgs
, double* ms
, GregorianDateTime
* t
)
269 double milliseconds
= 0;
272 int numArgs
= args
.size();
274 // JS allows extra trailing arguments -- ignore them
275 if (numArgs
> maxArgs
)
279 if (maxArgs
>= 4 && idx
< numArgs
) {
281 milliseconds
+= args
.at(idx
++).toInt32(exec
, ok
) * msPerHour
;
285 if (maxArgs
>= 3 && idx
< numArgs
&& ok
) {
287 milliseconds
+= args
.at(idx
++).toInt32(exec
, ok
) * msPerMinute
;
291 if (maxArgs
>= 2 && idx
< numArgs
&& ok
) {
293 milliseconds
+= args
.at(idx
++).toInt32(exec
, ok
) * msPerSecond
;
301 double millis
= args
.at(idx
).toNumber(exec
);
302 ok
= isfinite(millis
);
303 milliseconds
+= millis
;
311 // Converts a list of arguments sent to a Date member function into years, months, and milliseconds, updating
312 // ms (representing milliseconds) and t (representing the rest of the date structure) appropriately.
314 // Format of member function: f([years,] [months,] [days])
315 static bool fillStructuresUsingDateArgs(ExecState
*exec
, const ArgList
& args
, int maxArgs
, double *ms
, GregorianDateTime
*t
)
319 int numArgs
= args
.size();
321 // JS allows extra trailing arguments -- ignore them
322 if (numArgs
> maxArgs
)
326 if (maxArgs
>= 3 && idx
< numArgs
)
327 t
->year
= args
.at(idx
++).toInt32(exec
, ok
) - 1900;
330 if (maxArgs
>= 2 && idx
< numArgs
&& ok
)
331 t
->month
= args
.at(idx
++).toInt32(exec
, ok
);
334 if (idx
< numArgs
&& ok
) {
336 *ms
+= args
.at(idx
).toInt32(exec
, ok
) * msPerDay
;
342 const ClassInfo
DatePrototype::info
= {"Date", &DateInstance::info
, 0, ExecState::dateTable
};
344 /* Source for DatePrototype.lut.h
346 toString dateProtoFuncToString DontEnum|Function 0
347 toISOString dateProtoFuncToISOString DontEnum|Function 0
348 toUTCString dateProtoFuncToUTCString DontEnum|Function 0
349 toDateString dateProtoFuncToDateString DontEnum|Function 0
350 toTimeString dateProtoFuncToTimeString DontEnum|Function 0
351 toLocaleString dateProtoFuncToLocaleString DontEnum|Function 0
352 toLocaleDateString dateProtoFuncToLocaleDateString DontEnum|Function 0
353 toLocaleTimeString dateProtoFuncToLocaleTimeString DontEnum|Function 0
354 valueOf dateProtoFuncGetTime DontEnum|Function 0
355 getTime dateProtoFuncGetTime DontEnum|Function 0
356 getFullYear dateProtoFuncGetFullYear DontEnum|Function 0
357 getUTCFullYear dateProtoFuncGetUTCFullYear DontEnum|Function 0
358 toGMTString dateProtoFuncToGMTString DontEnum|Function 0
359 getMonth dateProtoFuncGetMonth DontEnum|Function 0
360 getUTCMonth dateProtoFuncGetUTCMonth DontEnum|Function 0
361 getDate dateProtoFuncGetDate DontEnum|Function 0
362 getUTCDate dateProtoFuncGetUTCDate DontEnum|Function 0
363 getDay dateProtoFuncGetDay DontEnum|Function 0
364 getUTCDay dateProtoFuncGetUTCDay DontEnum|Function 0
365 getHours dateProtoFuncGetHours DontEnum|Function 0
366 getUTCHours dateProtoFuncGetUTCHours DontEnum|Function 0
367 getMinutes dateProtoFuncGetMinutes DontEnum|Function 0
368 getUTCMinutes dateProtoFuncGetUTCMinutes DontEnum|Function 0
369 getSeconds dateProtoFuncGetSeconds DontEnum|Function 0
370 getUTCSeconds dateProtoFuncGetUTCSeconds DontEnum|Function 0
371 getMilliseconds dateProtoFuncGetMilliSeconds DontEnum|Function 0
372 getUTCMilliseconds dateProtoFuncGetUTCMilliseconds DontEnum|Function 0
373 getTimezoneOffset dateProtoFuncGetTimezoneOffset DontEnum|Function 0
374 setTime dateProtoFuncSetTime DontEnum|Function 1
375 setMilliseconds dateProtoFuncSetMilliSeconds DontEnum|Function 1
376 setUTCMilliseconds dateProtoFuncSetUTCMilliseconds DontEnum|Function 1
377 setSeconds dateProtoFuncSetSeconds DontEnum|Function 2
378 setUTCSeconds dateProtoFuncSetUTCSeconds DontEnum|Function 2
379 setMinutes dateProtoFuncSetMinutes DontEnum|Function 3
380 setUTCMinutes dateProtoFuncSetUTCMinutes DontEnum|Function 3
381 setHours dateProtoFuncSetHours DontEnum|Function 4
382 setUTCHours dateProtoFuncSetUTCHours DontEnum|Function 4
383 setDate dateProtoFuncSetDate DontEnum|Function 1
384 setUTCDate dateProtoFuncSetUTCDate DontEnum|Function 1
385 setMonth dateProtoFuncSetMonth DontEnum|Function 2
386 setUTCMonth dateProtoFuncSetUTCMonth DontEnum|Function 2
387 setFullYear dateProtoFuncSetFullYear DontEnum|Function 3
388 setUTCFullYear dateProtoFuncSetUTCFullYear DontEnum|Function 3
389 setYear dateProtoFuncSetYear DontEnum|Function 1
390 getYear dateProtoFuncGetYear DontEnum|Function 0
391 toJSON dateProtoFuncToJSON DontEnum|Function 0
397 DatePrototype::DatePrototype(ExecState
* exec
, NonNullPassRefPtr
<Structure
> structure
)
398 : DateInstance(exec
, structure
)
400 // The constructor will be added later, after DateConstructor has been built.
403 bool DatePrototype::getOwnPropertySlot(ExecState
* exec
, const Identifier
& propertyName
, PropertySlot
& slot
)
405 return getStaticFunctionSlot
<JSObject
>(exec
, ExecState::dateTable(exec
), this, propertyName
, slot
);
409 bool DatePrototype::getOwnPropertyDescriptor(ExecState
* exec
, const Identifier
& propertyName
, PropertyDescriptor
& descriptor
)
411 return getStaticFunctionDescriptor
<JSObject
>(exec
, ExecState::dateTable(exec
), this, propertyName
, descriptor
);
416 JSValue JSC_HOST_CALL
dateProtoFuncToString(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
&)
418 if (!thisValue
.inherits(&DateInstance::info
))
419 return throwError(exec
, TypeError
);
421 DateInstance
* thisDateObj
= asDateInstance(thisValue
);
423 const GregorianDateTime
* gregorianDateTime
= thisDateObj
->gregorianDateTime(exec
);
424 if (!gregorianDateTime
)
425 return jsNontrivialString(exec
, "Invalid Date");
426 DateConversionBuffer date
;
427 DateConversionBuffer time
;
428 formatDate(*gregorianDateTime
, date
);
429 formatTime(*gregorianDateTime
, time
);
430 return jsNontrivialString(exec
, makeString(date
, " ", time
));
433 JSValue JSC_HOST_CALL
dateProtoFuncToUTCString(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
&)
435 if (!thisValue
.inherits(&DateInstance::info
))
436 return throwError(exec
, TypeError
);
438 DateInstance
* thisDateObj
= asDateInstance(thisValue
);
440 const GregorianDateTime
* gregorianDateTime
= thisDateObj
->gregorianDateTimeUTC(exec
);
441 if (!gregorianDateTime
)
442 return jsNontrivialString(exec
, "Invalid Date");
443 DateConversionBuffer date
;
444 DateConversionBuffer time
;
445 formatDateUTCVariant(*gregorianDateTime
, date
);
446 formatTimeUTC(*gregorianDateTime
, time
);
447 return jsNontrivialString(exec
, makeString(date
, " ", time
));
450 JSValue JSC_HOST_CALL
dateProtoFuncToISOString(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
&)
452 if (!thisValue
.inherits(&DateInstance::info
))
453 return throwError(exec
, TypeError
);
455 DateInstance
* thisDateObj
= asDateInstance(thisValue
);
457 const GregorianDateTime
* gregorianDateTime
= thisDateObj
->gregorianDateTimeUTC(exec
);
458 if (!gregorianDateTime
)
459 return jsNontrivialString(exec
, "Invalid Date");
460 // Maximum amount of space we need in buffer: 6 (max. digits in year) + 2 * 5 (2 characters each for month, day, hour, minute, second) + 4 (. + 3 digits for milliseconds)
461 // 6 for formatting and one for null termination = 27. We add one extra character to allow us to force null termination.
463 snprintf(buffer
, sizeof(buffer
) - 1, "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", 1900 + gregorianDateTime
->year
, gregorianDateTime
->month
+ 1, gregorianDateTime
->monthDay
, gregorianDateTime
->hour
, gregorianDateTime
->minute
, gregorianDateTime
->second
, static_cast<int>(fmod(thisDateObj
->internalNumber(), 1000)));
464 buffer
[sizeof(buffer
) - 1] = 0;
465 return jsNontrivialString(exec
, buffer
);
468 JSValue JSC_HOST_CALL
dateProtoFuncToDateString(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
&)
470 if (!thisValue
.inherits(&DateInstance::info
))
471 return throwError(exec
, TypeError
);
473 DateInstance
* thisDateObj
= asDateInstance(thisValue
);
475 const GregorianDateTime
* gregorianDateTime
= thisDateObj
->gregorianDateTime(exec
);
476 if (!gregorianDateTime
)
477 return jsNontrivialString(exec
, "Invalid Date");
478 DateConversionBuffer date
;
479 formatDate(*gregorianDateTime
, date
);
480 return jsNontrivialString(exec
, date
);
483 JSValue JSC_HOST_CALL
dateProtoFuncToTimeString(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
&)
485 if (!thisValue
.inherits(&DateInstance::info
))
486 return throwError(exec
, TypeError
);
488 DateInstance
* thisDateObj
= asDateInstance(thisValue
);
490 const GregorianDateTime
* gregorianDateTime
= thisDateObj
->gregorianDateTime(exec
);
491 if (!gregorianDateTime
)
492 return jsNontrivialString(exec
, "Invalid Date");
493 DateConversionBuffer time
;
494 formatTime(*gregorianDateTime
, time
);
495 return jsNontrivialString(exec
, time
);
498 JSValue JSC_HOST_CALL
dateProtoFuncToLocaleString(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
& args
)
500 if (!thisValue
.inherits(&DateInstance::info
))
501 return throwError(exec
, TypeError
);
503 DateInstance
* thisDateObj
= asDateInstance(thisValue
);
504 return formatLocaleDate(exec
, thisDateObj
, thisDateObj
->internalNumber(), LocaleDateAndTime
, args
);
507 JSValue JSC_HOST_CALL
dateProtoFuncToLocaleDateString(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
& args
)
509 if (!thisValue
.inherits(&DateInstance::info
))
510 return throwError(exec
, TypeError
);
512 DateInstance
* thisDateObj
= asDateInstance(thisValue
);
513 return formatLocaleDate(exec
, thisDateObj
, thisDateObj
->internalNumber(), LocaleDate
, args
);
516 JSValue JSC_HOST_CALL
dateProtoFuncToLocaleTimeString(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
& args
)
518 if (!thisValue
.inherits(&DateInstance::info
))
519 return throwError(exec
, TypeError
);
521 DateInstance
* thisDateObj
= asDateInstance(thisValue
);
522 return formatLocaleDate(exec
, thisDateObj
, thisDateObj
->internalNumber(), LocaleTime
, args
);
525 JSValue JSC_HOST_CALL
dateProtoFuncGetTime(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
&)
527 if (!thisValue
.inherits(&DateInstance::info
))
528 return throwError(exec
, TypeError
);
530 return asDateInstance(thisValue
)->internalValue();
533 JSValue JSC_HOST_CALL
dateProtoFuncGetFullYear(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
&)
535 if (!thisValue
.inherits(&DateInstance::info
))
536 return throwError(exec
, TypeError
);
538 DateInstance
* thisDateObj
= asDateInstance(thisValue
);
540 const GregorianDateTime
* gregorianDateTime
= thisDateObj
->gregorianDateTime(exec
);
541 if (!gregorianDateTime
)
543 return jsNumber(exec
, 1900 + gregorianDateTime
->year
);
546 JSValue JSC_HOST_CALL
dateProtoFuncGetUTCFullYear(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
&)
548 if (!thisValue
.inherits(&DateInstance::info
))
549 return throwError(exec
, TypeError
);
551 DateInstance
* thisDateObj
= asDateInstance(thisValue
);
553 const GregorianDateTime
* gregorianDateTime
= thisDateObj
->gregorianDateTimeUTC(exec
);
554 if (!gregorianDateTime
)
556 return jsNumber(exec
, 1900 + gregorianDateTime
->year
);
559 JSValue JSC_HOST_CALL
dateProtoFuncToGMTString(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
&)
561 if (!thisValue
.inherits(&DateInstance::info
))
562 return throwError(exec
, TypeError
);
564 DateInstance
* thisDateObj
= asDateInstance(thisValue
);
566 const GregorianDateTime
* gregorianDateTime
= thisDateObj
->gregorianDateTimeUTC(exec
);
567 if (!gregorianDateTime
)
568 return jsNontrivialString(exec
, "Invalid Date");
569 DateConversionBuffer date
;
570 DateConversionBuffer time
;
571 formatDateUTCVariant(*gregorianDateTime
, date
);
572 formatTimeUTC(*gregorianDateTime
, time
);
573 return jsNontrivialString(exec
, makeString(date
, " ", time
));
576 JSValue JSC_HOST_CALL
dateProtoFuncGetMonth(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
&)
578 if (!thisValue
.inherits(&DateInstance::info
))
579 return throwError(exec
, TypeError
);
581 DateInstance
* thisDateObj
= asDateInstance(thisValue
);
583 const GregorianDateTime
* gregorianDateTime
= thisDateObj
->gregorianDateTime(exec
);
584 if (!gregorianDateTime
)
586 return jsNumber(exec
, gregorianDateTime
->month
);
589 JSValue JSC_HOST_CALL
dateProtoFuncGetUTCMonth(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
&)
591 if (!thisValue
.inherits(&DateInstance::info
))
592 return throwError(exec
, TypeError
);
594 DateInstance
* thisDateObj
= asDateInstance(thisValue
);
596 const GregorianDateTime
* gregorianDateTime
= thisDateObj
->gregorianDateTimeUTC(exec
);
597 if (!gregorianDateTime
)
599 return jsNumber(exec
, gregorianDateTime
->month
);
602 JSValue JSC_HOST_CALL
dateProtoFuncGetDate(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
&)
604 if (!thisValue
.inherits(&DateInstance::info
))
605 return throwError(exec
, TypeError
);
607 DateInstance
* thisDateObj
= asDateInstance(thisValue
);
609 const GregorianDateTime
* gregorianDateTime
= thisDateObj
->gregorianDateTime(exec
);
610 if (!gregorianDateTime
)
612 return jsNumber(exec
, gregorianDateTime
->monthDay
);
615 JSValue JSC_HOST_CALL
dateProtoFuncGetUTCDate(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
&)
617 if (!thisValue
.inherits(&DateInstance::info
))
618 return throwError(exec
, TypeError
);
620 DateInstance
* thisDateObj
= asDateInstance(thisValue
);
622 const GregorianDateTime
* gregorianDateTime
= thisDateObj
->gregorianDateTimeUTC(exec
);
623 if (!gregorianDateTime
)
625 return jsNumber(exec
, gregorianDateTime
->monthDay
);
628 JSValue JSC_HOST_CALL
dateProtoFuncGetDay(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
&)
630 if (!thisValue
.inherits(&DateInstance::info
))
631 return throwError(exec
, TypeError
);
633 DateInstance
* thisDateObj
= asDateInstance(thisValue
);
635 const GregorianDateTime
* gregorianDateTime
= thisDateObj
->gregorianDateTime(exec
);
636 if (!gregorianDateTime
)
638 return jsNumber(exec
, gregorianDateTime
->weekDay
);
641 JSValue JSC_HOST_CALL
dateProtoFuncGetUTCDay(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
&)
643 if (!thisValue
.inherits(&DateInstance::info
))
644 return throwError(exec
, TypeError
);
646 DateInstance
* thisDateObj
= asDateInstance(thisValue
);
648 const GregorianDateTime
* gregorianDateTime
= thisDateObj
->gregorianDateTimeUTC(exec
);
649 if (!gregorianDateTime
)
651 return jsNumber(exec
, gregorianDateTime
->weekDay
);
654 JSValue JSC_HOST_CALL
dateProtoFuncGetHours(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
&)
656 if (!thisValue
.inherits(&DateInstance::info
))
657 return throwError(exec
, TypeError
);
659 DateInstance
* thisDateObj
= asDateInstance(thisValue
);
661 const GregorianDateTime
* gregorianDateTime
= thisDateObj
->gregorianDateTime(exec
);
662 if (!gregorianDateTime
)
664 return jsNumber(exec
, gregorianDateTime
->hour
);
667 JSValue JSC_HOST_CALL
dateProtoFuncGetUTCHours(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
&)
669 if (!thisValue
.inherits(&DateInstance::info
))
670 return throwError(exec
, TypeError
);
672 DateInstance
* thisDateObj
= asDateInstance(thisValue
);
674 const GregorianDateTime
* gregorianDateTime
= thisDateObj
->gregorianDateTimeUTC(exec
);
675 if (!gregorianDateTime
)
677 return jsNumber(exec
, gregorianDateTime
->hour
);
680 JSValue JSC_HOST_CALL
dateProtoFuncGetMinutes(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
&)
682 if (!thisValue
.inherits(&DateInstance::info
))
683 return throwError(exec
, TypeError
);
685 DateInstance
* thisDateObj
= asDateInstance(thisValue
);
687 const GregorianDateTime
* gregorianDateTime
= thisDateObj
->gregorianDateTime(exec
);
688 if (!gregorianDateTime
)
690 return jsNumber(exec
, gregorianDateTime
->minute
);
693 JSValue JSC_HOST_CALL
dateProtoFuncGetUTCMinutes(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
&)
695 if (!thisValue
.inherits(&DateInstance::info
))
696 return throwError(exec
, TypeError
);
698 DateInstance
* thisDateObj
= asDateInstance(thisValue
);
700 const GregorianDateTime
* gregorianDateTime
= thisDateObj
->gregorianDateTimeUTC(exec
);
701 if (!gregorianDateTime
)
703 return jsNumber(exec
, gregorianDateTime
->minute
);
706 JSValue JSC_HOST_CALL
dateProtoFuncGetSeconds(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
&)
708 if (!thisValue
.inherits(&DateInstance::info
))
709 return throwError(exec
, TypeError
);
711 DateInstance
* thisDateObj
= asDateInstance(thisValue
);
713 const GregorianDateTime
* gregorianDateTime
= thisDateObj
->gregorianDateTime(exec
);
714 if (!gregorianDateTime
)
716 return jsNumber(exec
, gregorianDateTime
->second
);
719 JSValue JSC_HOST_CALL
dateProtoFuncGetUTCSeconds(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
&)
721 if (!thisValue
.inherits(&DateInstance::info
))
722 return throwError(exec
, TypeError
);
724 DateInstance
* thisDateObj
= asDateInstance(thisValue
);
726 const GregorianDateTime
* gregorianDateTime
= thisDateObj
->gregorianDateTimeUTC(exec
);
727 if (!gregorianDateTime
)
729 return jsNumber(exec
, gregorianDateTime
->second
);
732 JSValue JSC_HOST_CALL
dateProtoFuncGetMilliSeconds(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
&)
734 if (!thisValue
.inherits(&DateInstance::info
))
735 return throwError(exec
, TypeError
);
737 DateInstance
* thisDateObj
= asDateInstance(thisValue
);
738 double milli
= thisDateObj
->internalNumber();
742 double secs
= floor(milli
/ msPerSecond
);
743 double ms
= milli
- secs
* msPerSecond
;
744 return jsNumber(exec
, ms
);
747 JSValue JSC_HOST_CALL
dateProtoFuncGetUTCMilliseconds(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
&)
749 if (!thisValue
.inherits(&DateInstance::info
))
750 return throwError(exec
, TypeError
);
752 DateInstance
* thisDateObj
= asDateInstance(thisValue
);
753 double milli
= thisDateObj
->internalNumber();
757 double secs
= floor(milli
/ msPerSecond
);
758 double ms
= milli
- secs
* msPerSecond
;
759 return jsNumber(exec
, ms
);
762 JSValue JSC_HOST_CALL
dateProtoFuncGetTimezoneOffset(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
&)
764 if (!thisValue
.inherits(&DateInstance::info
))
765 return throwError(exec
, TypeError
);
767 DateInstance
* thisDateObj
= asDateInstance(thisValue
);
769 const GregorianDateTime
* gregorianDateTime
= thisDateObj
->gregorianDateTime(exec
);
770 if (!gregorianDateTime
)
772 return jsNumber(exec
, -gregorianDateTime
->utcOffset
/ minutesPerHour
);
775 JSValue JSC_HOST_CALL
dateProtoFuncSetTime(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
& args
)
777 if (!thisValue
.inherits(&DateInstance::info
))
778 return throwError(exec
, TypeError
);
780 DateInstance
* thisDateObj
= asDateInstance(thisValue
);
782 double milli
= timeClip(args
.at(0).toNumber(exec
));
783 JSValue result
= jsNumber(exec
, milli
);
784 thisDateObj
->setInternalValue(result
);
788 static JSValue
setNewValueFromTimeArgs(ExecState
* exec
, JSValue thisValue
, const ArgList
& args
, int numArgsToUse
, bool inputIsUTC
)
790 if (!thisValue
.inherits(&DateInstance::info
))
791 return throwError(exec
, TypeError
);
793 DateInstance
* thisDateObj
= asDateInstance(thisValue
);
794 double milli
= thisDateObj
->internalNumber();
796 if (args
.isEmpty() || isnan(milli
)) {
797 JSValue result
= jsNaN(exec
);
798 thisDateObj
->setInternalValue(result
);
802 double secs
= floor(milli
/ msPerSecond
);
803 double ms
= milli
- secs
* msPerSecond
;
805 const GregorianDateTime
* other
= inputIsUTC
806 ? thisDateObj
->gregorianDateTimeUTC(exec
)
807 : thisDateObj
->gregorianDateTime(exec
);
811 GregorianDateTime gregorianDateTime
;
812 gregorianDateTime
.copyFrom(*other
);
813 if (!fillStructuresUsingTimeArgs(exec
, args
, numArgsToUse
, &ms
, &gregorianDateTime
)) {
814 JSValue result
= jsNaN(exec
);
815 thisDateObj
->setInternalValue(result
);
819 JSValue result
= jsNumber(exec
, gregorianDateTimeToMS(exec
, gregorianDateTime
, ms
, inputIsUTC
));
820 thisDateObj
->setInternalValue(result
);
824 static JSValue
setNewValueFromDateArgs(ExecState
* exec
, JSValue thisValue
, const ArgList
& args
, int numArgsToUse
, bool inputIsUTC
)
826 if (!thisValue
.inherits(&DateInstance::info
))
827 return throwError(exec
, TypeError
);
829 DateInstance
* thisDateObj
= asDateInstance(thisValue
);
830 if (args
.isEmpty()) {
831 JSValue result
= jsNaN(exec
);
832 thisDateObj
->setInternalValue(result
);
836 double milli
= thisDateObj
->internalNumber();
839 GregorianDateTime gregorianDateTime
;
840 if (numArgsToUse
== 3 && isnan(milli
))
841 msToGregorianDateTime(exec
, 0, true, gregorianDateTime
);
843 ms
= milli
- floor(milli
/ msPerSecond
) * msPerSecond
;
844 const GregorianDateTime
* other
= inputIsUTC
845 ? thisDateObj
->gregorianDateTimeUTC(exec
)
846 : thisDateObj
->gregorianDateTime(exec
);
849 gregorianDateTime
.copyFrom(*other
);
852 if (!fillStructuresUsingDateArgs(exec
, args
, numArgsToUse
, &ms
, &gregorianDateTime
)) {
853 JSValue result
= jsNaN(exec
);
854 thisDateObj
->setInternalValue(result
);
858 JSValue result
= jsNumber(exec
, gregorianDateTimeToMS(exec
, gregorianDateTime
, ms
, inputIsUTC
));
859 thisDateObj
->setInternalValue(result
);
863 JSValue JSC_HOST_CALL
dateProtoFuncSetMilliSeconds(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
& args
)
865 const bool inputIsUTC
= false;
866 return setNewValueFromTimeArgs(exec
, thisValue
, args
, 1, inputIsUTC
);
869 JSValue JSC_HOST_CALL
dateProtoFuncSetUTCMilliseconds(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
& args
)
871 const bool inputIsUTC
= true;
872 return setNewValueFromTimeArgs(exec
, thisValue
, args
, 1, inputIsUTC
);
875 JSValue JSC_HOST_CALL
dateProtoFuncSetSeconds(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
& args
)
877 const bool inputIsUTC
= false;
878 return setNewValueFromTimeArgs(exec
, thisValue
, args
, 2, inputIsUTC
);
881 JSValue JSC_HOST_CALL
dateProtoFuncSetUTCSeconds(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
& args
)
883 const bool inputIsUTC
= true;
884 return setNewValueFromTimeArgs(exec
, thisValue
, args
, 2, inputIsUTC
);
887 JSValue JSC_HOST_CALL
dateProtoFuncSetMinutes(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
& args
)
889 const bool inputIsUTC
= false;
890 return setNewValueFromTimeArgs(exec
, thisValue
, args
, 3, inputIsUTC
);
893 JSValue JSC_HOST_CALL
dateProtoFuncSetUTCMinutes(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
& args
)
895 const bool inputIsUTC
= true;
896 return setNewValueFromTimeArgs(exec
, thisValue
, args
, 3, inputIsUTC
);
899 JSValue JSC_HOST_CALL
dateProtoFuncSetHours(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
& args
)
901 const bool inputIsUTC
= false;
902 return setNewValueFromTimeArgs(exec
, thisValue
, args
, 4, inputIsUTC
);
905 JSValue JSC_HOST_CALL
dateProtoFuncSetUTCHours(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
& args
)
907 const bool inputIsUTC
= true;
908 return setNewValueFromTimeArgs(exec
, thisValue
, args
, 4, inputIsUTC
);
911 JSValue JSC_HOST_CALL
dateProtoFuncSetDate(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
& args
)
913 const bool inputIsUTC
= false;
914 return setNewValueFromDateArgs(exec
, thisValue
, args
, 1, inputIsUTC
);
917 JSValue JSC_HOST_CALL
dateProtoFuncSetUTCDate(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
& args
)
919 const bool inputIsUTC
= true;
920 return setNewValueFromDateArgs(exec
, thisValue
, args
, 1, inputIsUTC
);
923 JSValue JSC_HOST_CALL
dateProtoFuncSetMonth(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
& args
)
925 const bool inputIsUTC
= false;
926 return setNewValueFromDateArgs(exec
, thisValue
, args
, 2, inputIsUTC
);
929 JSValue JSC_HOST_CALL
dateProtoFuncSetUTCMonth(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
& args
)
931 const bool inputIsUTC
= true;
932 return setNewValueFromDateArgs(exec
, thisValue
, args
, 2, inputIsUTC
);
935 JSValue JSC_HOST_CALL
dateProtoFuncSetFullYear(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
& args
)
937 const bool inputIsUTC
= false;
938 return setNewValueFromDateArgs(exec
, thisValue
, args
, 3, inputIsUTC
);
941 JSValue JSC_HOST_CALL
dateProtoFuncSetUTCFullYear(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
& args
)
943 const bool inputIsUTC
= true;
944 return setNewValueFromDateArgs(exec
, thisValue
, args
, 3, inputIsUTC
);
947 JSValue JSC_HOST_CALL
dateProtoFuncSetYear(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
& args
)
949 if (!thisValue
.inherits(&DateInstance::info
))
950 return throwError(exec
, TypeError
);
952 DateInstance
* thisDateObj
= asDateInstance(thisValue
);
953 if (args
.isEmpty()) {
954 JSValue result
= jsNaN(exec
);
955 thisDateObj
->setInternalValue(result
);
959 double milli
= thisDateObj
->internalNumber();
962 GregorianDateTime gregorianDateTime
;
964 // Based on ECMA 262 B.2.5 (setYear)
965 // the time must be reset to +0 if it is NaN.
966 msToGregorianDateTime(exec
, 0, true, gregorianDateTime
);
968 double secs
= floor(milli
/ msPerSecond
);
969 ms
= milli
- secs
* msPerSecond
;
970 if (const GregorianDateTime
* other
= thisDateObj
->gregorianDateTime(exec
))
971 gregorianDateTime
.copyFrom(*other
);
975 int32_t year
= args
.at(0).toInt32(exec
, ok
);
977 JSValue result
= jsNaN(exec
);
978 thisDateObj
->setInternalValue(result
);
982 gregorianDateTime
.year
= (year
> 99 || year
< 0) ? year
- 1900 : year
;
983 JSValue result
= jsNumber(exec
, gregorianDateTimeToMS(exec
, gregorianDateTime
, ms
, false));
984 thisDateObj
->setInternalValue(result
);
988 JSValue JSC_HOST_CALL
dateProtoFuncGetYear(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
&)
990 if (!thisValue
.inherits(&DateInstance::info
))
991 return throwError(exec
, TypeError
);
993 DateInstance
* thisDateObj
= asDateInstance(thisValue
);
995 const GregorianDateTime
* gregorianDateTime
= thisDateObj
->gregorianDateTime(exec
);
996 if (!gregorianDateTime
)
999 // NOTE: IE returns the full year even in getYear.
1000 return jsNumber(exec
, gregorianDateTime
->year
);
1003 JSValue JSC_HOST_CALL
dateProtoFuncToJSON(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
&)
1005 JSObject
* object
= thisValue
.toThisObject(exec
);
1006 if (exec
->hadException())
1009 JSValue toISOValue
= object
->get(exec
, exec
->globalData().propertyNames
->toISOString
);
1010 if (exec
->hadException())
1014 CallType callType
= toISOValue
.getCallData(callData
);
1015 if (callType
== CallTypeNone
)
1016 return throwError(exec
, TypeError
, "toISOString is not a function");
1018 JSValue result
= call(exec
, asObject(toISOValue
), callType
, callData
, object
, exec
->emptyList());
1019 if (exec
->hadException())
1021 if (result
.isObject())
1022 return throwError(exec
, TypeError
, "toISOString did not return a primitive value");