2 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
23 #include "date_object.h"
24 #include "date_object.lut.h"
32 #include <sys/param.h>
40 #include <sys/timeb.h>
52 #include "error_object.h"
53 #include "operations.h"
56 #include <wtf/ASCIICType.h>
57 #include <wtf/Assertions.h>
58 #include <wtf/MathExtras.h>
59 #include <wtf/StringExtras.h>
60 #include <wtf/UnusedParam.h>
62 #include <CoreFoundation/CoreFoundation.h>
68 static double parseDate(const UString
&);
69 static double timeClip(double);
71 inline int gmtoffset(const GregorianDateTime
& t
)
80 * Class to implement all methods that are properties of the
83 class DateObjectFuncImp
: public InternalFunctionImp
{
85 DateObjectFuncImp(ExecState
*, FunctionPrototype
*, int i
, int len
, const Identifier
& );
87 virtual JSValue
*callAsFunction(ExecState
*, JSObject
*thisObj
, const List
&args
);
96 static CFDateFormatterStyle
styleFromArgString(const UString
& string
, CFDateFormatterStyle defaultStyle
)
98 if (string
== "short")
99 return kCFDateFormatterShortStyle
;
100 if (string
== "medium")
101 return kCFDateFormatterMediumStyle
;
102 if (string
== "long")
103 return kCFDateFormatterLongStyle
;
104 if (string
== "full")
105 return kCFDateFormatterFullStyle
;
109 static UString
formatLocaleDate(ExecState
*exec
, double time
, bool includeDate
, bool includeTime
, const List
&args
)
111 CFDateFormatterStyle dateStyle
= (includeDate
? kCFDateFormatterLongStyle
: kCFDateFormatterNoStyle
);
112 CFDateFormatterStyle timeStyle
= (includeTime
? kCFDateFormatterLongStyle
: kCFDateFormatterNoStyle
);
114 bool useCustomFormat
= false;
115 UString customFormatString
;
117 UString arg0String
= args
[0]->toString(exec
);
118 if (arg0String
== "custom" && !args
[1]->isUndefined()) {
119 useCustomFormat
= true;
120 customFormatString
= args
[1]->toString(exec
);
121 } else if (includeDate
&& includeTime
&& !args
[1]->isUndefined()) {
122 dateStyle
= styleFromArgString(arg0String
, dateStyle
);
123 timeStyle
= styleFromArgString(args
[1]->toString(exec
), timeStyle
);
124 } else if (includeDate
&& !args
[0]->isUndefined()) {
125 dateStyle
= styleFromArgString(arg0String
, dateStyle
);
126 } else if (includeTime
&& !args
[0]->isUndefined()) {
127 timeStyle
= styleFromArgString(arg0String
, timeStyle
);
130 CFLocaleRef locale
= CFLocaleCopyCurrent();
131 CFDateFormatterRef formatter
= CFDateFormatterCreate(0, locale
, dateStyle
, timeStyle
);
134 if (useCustomFormat
) {
135 CFStringRef customFormatCFString
= CFStringCreateWithCharacters(0, (UniChar
*)customFormatString
.data(), customFormatString
.size());
136 CFDateFormatterSetFormat(formatter
, customFormatCFString
);
137 CFRelease(customFormatCFString
);
140 CFStringRef string
= CFDateFormatterCreateStringWithAbsoluteTime(0, formatter
, time
- kCFAbsoluteTimeIntervalSince1970
);
142 CFRelease(formatter
);
144 // We truncate the string returned from CFDateFormatter if it's absurdly long (> 200 characters).
145 // That's not great error handling, but it just won't happen so it doesn't matter.
147 const size_t bufferLength
= sizeof(buffer
) / sizeof(buffer
[0]);
148 size_t length
= CFStringGetLength(string
);
149 ASSERT(length
<= bufferLength
);
150 if (length
> bufferLength
)
151 length
= bufferLength
;
152 CFStringGetCharacters(string
, CFRangeMake(0, length
), reinterpret_cast<UniChar
*>(buffer
));
156 return UString(buffer
, length
);
160 static UString
formatDate(const GregorianDateTime
&t
)
163 snprintf(buffer
, sizeof(buffer
), "%s %s %02d %04d",
164 weekdayName
[(t
.weekDay
+ 6) % 7],
165 monthName
[t
.month
], t
.monthDay
, t
.year
+ 1900);
169 static UString
formatDateUTCVariant(const GregorianDateTime
&t
)
172 snprintf(buffer
, sizeof(buffer
), "%s, %02d %s %04d",
173 weekdayName
[(t
.weekDay
+ 6) % 7],
174 t
.monthDay
, monthName
[t
.month
], t
.year
+ 1900);
178 static UString
formatTime(const GregorianDateTime
&t
, bool utc
)
182 snprintf(buffer
, sizeof(buffer
), "%02d:%02d:%02d GMT", t
.hour
, t
.minute
, t
.second
);
184 int offset
= abs(gmtoffset(t
));
187 strftime(tzname
, sizeof(tzname
), "%Z", >m
);
190 snprintf(buffer
, sizeof(buffer
), "%02d:%02d:%02d GMT%c%02d%02d (%s)",
191 t
.hour
, t
.minute
, t
.second
,
192 gmtoffset(t
) < 0 ? '-' : '+', offset
/ (60*60), (offset
/ 60) % 60, tzname
);
194 snprintf(buffer
, sizeof(buffer
), "%02d:%02d:%02d GMT%c%02d%02d",
195 t
.hour
, t
.minute
, t
.second
,
196 gmtoffset(t
) < 0 ? '-' : '+', offset
/ (60*60), (offset
/ 60) % 60);
199 return UString(buffer
);
202 // Converts a list of arguments sent to a Date member function into milliseconds, updating
203 // ms (representing milliseconds) and t (representing the rest of the date structure) appropriately.
205 // Format of member function: f([hour,] [min,] [sec,] [ms])
206 static void fillStructuresUsingTimeArgs(ExecState
* exec
, const List
& args
, int maxArgs
, double* ms
, GregorianDateTime
* t
)
208 double milliseconds
= 0;
210 int numArgs
= args
.size();
212 // JS allows extra trailing arguments -- ignore them
213 if (numArgs
> maxArgs
)
217 if (maxArgs
>= 4 && idx
< numArgs
) {
219 milliseconds
+= args
[idx
++]->toInt32(exec
) * msPerHour
;
223 if (maxArgs
>= 3 && idx
< numArgs
) {
225 milliseconds
+= args
[idx
++]->toInt32(exec
) * msPerMinute
;
229 if (maxArgs
>= 2 && idx
< numArgs
) {
231 milliseconds
+= args
[idx
++]->toInt32(exec
) * msPerSecond
;
236 milliseconds
+= args
[idx
]->toNumber(exec
);
243 // Converts a list of arguments sent to a Date member function into years, months, and milliseconds, updating
244 // ms (representing milliseconds) and t (representing the rest of the date structure) appropriately.
246 // Format of member function: f([years,] [months,] [days])
247 static void fillStructuresUsingDateArgs(ExecState
*exec
, const List
&args
, int maxArgs
, double *ms
, GregorianDateTime
*t
)
250 int numArgs
= args
.size();
252 // JS allows extra trailing arguments -- ignore them
253 if (numArgs
> maxArgs
)
257 if (maxArgs
>= 3 && idx
< numArgs
)
258 t
->year
= args
[idx
++]->toInt32(exec
) - 1900;
261 if (maxArgs
>= 2 && idx
< numArgs
)
262 t
->month
= args
[idx
++]->toInt32(exec
);
267 *ms
+= args
[idx
]->toInt32(exec
) * msPerDay
;
271 // ------------------------------ DateInstance ------------------------------
273 const ClassInfo
DateInstance::info
= {"Date", 0, 0};
275 DateInstance::DateInstance(JSObject
*proto
)
276 : JSWrapperObject(proto
)
280 bool DateInstance::getTime(GregorianDateTime
&t
, int &offset
) const
282 double milli
= internalValue()->getNumber();
286 msToGregorianDateTime(milli
, false, t
);
287 offset
= gmtoffset(t
);
291 bool DateInstance::getUTCTime(GregorianDateTime
&t
) const
293 double milli
= internalValue()->getNumber();
297 msToGregorianDateTime(milli
, true, t
);
301 bool DateInstance::getTime(double &milli
, int &offset
) const
303 milli
= internalValue()->getNumber();
308 msToGregorianDateTime(milli
, false, t
);
309 offset
= gmtoffset(t
);
313 bool DateInstance::getUTCTime(double &milli
) const
315 milli
= internalValue()->getNumber();
322 static inline bool isTime_tSigned()
324 time_t minusOne
= (time_t)(-1);
328 // ------------------------------ DatePrototype -----------------------------
330 const ClassInfo
DatePrototype::info
= {"Date", &DateInstance::info
, &dateTable
};
332 /* Source for date_object.lut.h
333 FIXMEL We could use templates to simplify the UTC variants.
335 toString dateProtoFuncToString DontEnum|Function 0
336 toUTCString dateProtoFuncToUTCString DontEnum|Function 0
337 toDateString dateProtoFuncToDateString DontEnum|Function 0
338 toTimeString dateProtoFuncToTimeString DontEnum|Function 0
339 toLocaleString dateProtoFuncToLocaleString DontEnum|Function 0
340 toLocaleDateString dateProtoFuncToLocaleDateString DontEnum|Function 0
341 toLocaleTimeString dateProtoFuncToLocaleTimeString DontEnum|Function 0
342 valueOf dateProtoFuncValueOf DontEnum|Function 0
343 getTime dateProtoFuncGetTime DontEnum|Function 0
344 getFullYear dateProtoFuncGetFullYear DontEnum|Function 0
345 getUTCFullYear dateProtoFuncGetUTCFullYear DontEnum|Function 0
346 toGMTString dateProtoFuncToGMTString DontEnum|Function 0
347 getMonth dateProtoFuncGetMonth DontEnum|Function 0
348 getUTCMonth dateProtoFuncGetUTCMonth DontEnum|Function 0
349 getDate dateProtoFuncGetDate DontEnum|Function 0
350 getUTCDate dateProtoFuncGetUTCDate DontEnum|Function 0
351 getDay dateProtoFuncGetDay DontEnum|Function 0
352 getUTCDay dateProtoFuncGetUTCDay DontEnum|Function 0
353 getHours dateProtoFuncGetHours DontEnum|Function 0
354 getUTCHours dateProtoFuncGetUTCHours DontEnum|Function 0
355 getMinutes dateProtoFuncGetMinutes DontEnum|Function 0
356 getUTCMinutes dateProtoFuncGetUTCMinutes DontEnum|Function 0
357 getSeconds dateProtoFuncGetSeconds DontEnum|Function 0
358 getUTCSeconds dateProtoFuncGetUTCSeconds DontEnum|Function 0
359 getMilliseconds dateProtoFuncGetMilliSeconds DontEnum|Function 0
360 getUTCMilliseconds dateProtoFuncGetUTCMilliseconds DontEnum|Function 0
361 getTimezoneOffset dateProtoFuncGetTimezoneOffset DontEnum|Function 0
362 setTime dateProtoFuncSetTime DontEnum|Function 1
363 setMilliseconds dateProtoFuncSetMilliSeconds DontEnum|Function 1
364 setUTCMilliseconds dateProtoFuncSetUTCMilliseconds DontEnum|Function 1
365 setSeconds dateProtoFuncSetSeconds DontEnum|Function 2
366 setUTCSeconds dateProtoFuncSetUTCSeconds DontEnum|Function 2
367 setMinutes dateProtoFuncSetMinutes DontEnum|Function 3
368 setUTCMinutes dateProtoFuncSetUTCMinutes DontEnum|Function 3
369 setHours dateProtoFuncSetHours DontEnum|Function 4
370 setUTCHours dateProtoFuncSetUTCHours DontEnum|Function 4
371 setDate dateProtoFuncSetDate DontEnum|Function 1
372 setUTCDate dateProtoFuncSetUTCDate DontEnum|Function 1
373 setMonth dateProtoFuncSetMonth DontEnum|Function 2
374 setUTCMonth dateProtoFuncSetUTCMonth DontEnum|Function 2
375 setFullYear dateProtoFuncSetFullYear DontEnum|Function 3
376 setUTCFullYear dateProtoFuncSetUTCFullYear DontEnum|Function 3
377 setYear dateProtoFuncSetYear DontEnum|Function 1
378 getYear dateProtoFuncGetYear DontEnum|Function 0
383 DatePrototype::DatePrototype(ExecState
*, ObjectPrototype
*objectProto
)
384 : DateInstance(objectProto
)
386 setInternalValue(jsNaN());
387 // The constructor will be added later, after DateObjectImp has been built.
390 bool DatePrototype::getOwnPropertySlot(ExecState
* exec
, const Identifier
& propertyName
, PropertySlot
& slot
)
392 return getStaticFunctionSlot
<JSObject
>(exec
, &dateTable
, this, propertyName
, slot
);
395 // ------------------------------ DateObjectImp --------------------------------
397 // TODO: MakeTime (15.9.11.1) etc. ?
399 DateObjectImp::DateObjectImp(ExecState
* exec
, FunctionPrototype
* funcProto
, DatePrototype
* dateProto
)
400 : InternalFunctionImp(funcProto
, dateProto
->classInfo()->className
)
402 static const Identifier
* parsePropertyName
= new Identifier("parse");
403 static const Identifier
* UTCPropertyName
= new Identifier("UTC");
405 putDirect(exec
->propertyNames().prototype
, dateProto
, DontEnum
|DontDelete
|ReadOnly
);
406 putDirectFunction(new DateObjectFuncImp(exec
, funcProto
, DateObjectFuncImp::Parse
, 1, *parsePropertyName
), DontEnum
);
407 putDirectFunction(new DateObjectFuncImp(exec
, funcProto
, DateObjectFuncImp::UTC
, 7, *UTCPropertyName
), DontEnum
);
408 putDirect(exec
->propertyNames().length
, 7, ReadOnly
|DontDelete
|DontEnum
);
411 bool DateObjectImp::implementsConstruct() const
417 JSObject
*DateObjectImp::construct(ExecState
*exec
, const List
&args
)
419 int numArgs
= args
.size();
423 if (numArgs
== 0) { // new Date() ECMA 15.9.3.3
424 value
= getCurrentUTCTime();
425 } else if (numArgs
== 1) {
426 if (args
[0]->isObject(&DateInstance::info
))
427 value
= static_cast<DateInstance
*>(args
[0])->internalValue()->toNumber(exec
);
429 JSValue
* primitive
= args
[0]->toPrimitive(exec
);
430 if (primitive
->isString())
431 value
= parseDate(primitive
->getString());
433 value
= primitive
->toNumber(exec
);
436 if (isnan(args
[0]->toNumber(exec
))
437 || isnan(args
[1]->toNumber(exec
))
438 || (numArgs
>= 3 && isnan(args
[2]->toNumber(exec
)))
439 || (numArgs
>= 4 && isnan(args
[3]->toNumber(exec
)))
440 || (numArgs
>= 5 && isnan(args
[4]->toNumber(exec
)))
441 || (numArgs
>= 6 && isnan(args
[5]->toNumber(exec
)))
442 || (numArgs
>= 7 && isnan(args
[6]->toNumber(exec
)))) {
446 int year
= args
[0]->toInt32(exec
);
447 t
.year
= (year
>= 0 && year
<= 99) ? year
: year
- 1900;
448 t
.month
= args
[1]->toInt32(exec
);
449 t
.monthDay
= (numArgs
>= 3) ? args
[2]->toInt32(exec
) : 1;
450 t
.hour
= args
[3]->toInt32(exec
);
451 t
.minute
= args
[4]->toInt32(exec
);
452 t
.second
= args
[5]->toInt32(exec
);
454 double ms
= (numArgs
>= 7) ? args
[6]->toNumber(exec
) : 0;
455 value
= gregorianDateTimeToMS(t
, ms
, false);
459 DateInstance
*ret
= new DateInstance(exec
->lexicalGlobalObject()->datePrototype());
460 ret
->setInternalValue(jsNumber(timeClip(value
)));
465 JSValue
*DateObjectImp::callAsFunction(ExecState
* /*exec*/, JSObject
* /*thisObj*/, const List
&/*args*/)
468 GregorianDateTime
ts(*localtime(&t
));
469 return jsString(formatDate(ts
) + " " + formatTime(ts
, false));
472 // ------------------------------ DateObjectFuncImp ----------------------------
474 DateObjectFuncImp::DateObjectFuncImp(ExecState
* exec
, FunctionPrototype
* funcProto
, int i
, int len
, const Identifier
& name
)
475 : InternalFunctionImp(funcProto
, name
), id(i
)
477 putDirect(exec
->propertyNames().length
, len
, DontDelete
|ReadOnly
|DontEnum
);
481 JSValue
*DateObjectFuncImp::callAsFunction(ExecState
* exec
, JSObject
*, const List
& args
)
484 return jsNumber(parseDate(args
[0]->toString(exec
)));
488 if (isnan(args
[0]->toNumber(exec
))
489 || isnan(args
[1]->toNumber(exec
))
490 || (n
>= 3 && isnan(args
[2]->toNumber(exec
)))
491 || (n
>= 4 && isnan(args
[3]->toNumber(exec
)))
492 || (n
>= 5 && isnan(args
[4]->toNumber(exec
)))
493 || (n
>= 6 && isnan(args
[5]->toNumber(exec
)))
494 || (n
>= 7 && isnan(args
[6]->toNumber(exec
)))) {
499 memset(&t
, 0, sizeof(t
));
500 int year
= args
[0]->toInt32(exec
);
501 t
.year
= (year
>= 0 && year
<= 99) ? year
: year
- 1900;
502 t
.month
= args
[1]->toInt32(exec
);
503 t
.monthDay
= (n
>= 3) ? args
[2]->toInt32(exec
) : 1;
504 t
.hour
= args
[3]->toInt32(exec
);
505 t
.minute
= args
[4]->toInt32(exec
);
506 t
.second
= args
[5]->toInt32(exec
);
507 double ms
= (n
>= 7) ? args
[6]->toNumber(exec
) : 0;
508 return jsNumber(gregorianDateTimeToMS(t
, ms
, true));
512 // -----------------------------------------------------------------------------
514 // Code originally from krfcdate.cpp, but we don't want to use kdecore, and we want double range.
516 static inline double ymdhmsToSeconds(long year
, int mon
, int day
, int hour
, int minute
, int second
)
518 double days
= (day
- 32075)
519 + floor(1461 * (year
+ 4800.0 + (mon
- 14) / 12) / 4)
520 + 367 * (mon
- 2 - (mon
- 14) / 12 * 12) / 12
521 - floor(3 * ((year
+ 4900.0 + (mon
- 14) / 12) / 100) / 4)
523 return ((days
* hoursPerDay
+ hour
) * minutesPerHour
+ minute
) * secondsPerMinute
+ second
;
526 // We follow the recommendation of RFC 2822 to consider all
527 // obsolete time zones not listed here equivalent to "-0000".
528 static const struct KnownZone
{
529 #if !PLATFORM(WIN_OS)
547 inline static void skipSpacesAndComments(const char*& s
)
552 if (!isASCIISpace(ch
)) {
555 else if (ch
== ')' && nesting
> 0)
557 else if (nesting
== 0)
564 // returns 0-11 (Jan-Dec); -1 on failure
565 static int findMonth(const char* monthStr
)
569 for (int i
= 0; i
< 3; ++i
) {
572 needle
[i
] = static_cast<char>(toASCIILower(*monthStr
++));
575 const char *haystack
= "janfebmaraprmayjunjulaugsepoctnovdec";
576 const char *str
= strstr(haystack
, needle
);
578 int position
= static_cast<int>(str
- haystack
);
579 if (position
% 3 == 0)
585 static double parseDate(const UString
&date
)
587 // This parses a date in the form:
588 // Tuesday, 09-Nov-99 23:12:40 GMT
590 // Sat, 01-Jan-2000 08:00:00 GMT
592 // Sat, 01 Jan 2000 08:00:00 GMT
594 // 01 Jan 99 22:00 +0100 (exceptions in rfc822/rfc2822)
595 // ### non RFC formats, added for Javascript:
596 // [Wednesday] January 09 1999 23:12:40 GMT
597 // [Wednesday] January 09 23:12:40 GMT 1999
599 // We ignore the weekday.
601 CString dateCString
= date
.UTF8String();
602 const char *dateString
= dateCString
.c_str();
604 // Skip leading space
605 skipSpacesAndComments(dateString
);
608 const char *wordStart
= dateString
;
609 // Check contents of first words if not number
610 while (*dateString
&& !isASCIIDigit(*dateString
)) {
611 if (isASCIISpace(*dateString
) || *dateString
== '(') {
612 if (dateString
- wordStart
>= 3)
613 month
= findMonth(wordStart
);
614 skipSpacesAndComments(dateString
);
615 wordStart
= dateString
;
620 // Missing delimiter between month and day (like "January29")?
621 if (month
== -1 && wordStart
!= dateString
)
622 month
= findMonth(wordStart
);
624 skipSpacesAndComments(dateString
);
629 // ' 09-Nov-99 23:12:40 GMT'
632 long day
= strtol(dateString
, &newPosStr
, 10);
635 dateString
= newPosStr
;
645 // ### where is the boundary and what happens below?
646 if (*dateString
!= '/')
648 // looks like a YYYY/MM/DD date
652 month
= strtol(dateString
, &newPosStr
, 10) - 1;
655 dateString
= newPosStr
;
656 if (*dateString
++ != '/' || !*dateString
)
658 day
= strtol(dateString
, &newPosStr
, 10);
661 dateString
= newPosStr
;
662 } else if (*dateString
== '/' && month
== -1) {
664 // This looks like a MM/DD/YYYY date, not an RFC date.
665 month
= day
- 1; // 0-based
666 day
= strtol(dateString
, &newPosStr
, 10);
669 if (day
< 1 || day
> 31)
671 dateString
= newPosStr
;
672 if (*dateString
== '/')
677 if (*dateString
== '-')
680 skipSpacesAndComments(dateString
);
682 if (*dateString
== ',')
685 if (month
== -1) { // not found yet
686 month
= findMonth(dateString
);
690 while (*dateString
&& *dateString
!= '-' && *dateString
!= ',' && !isASCIISpace(*dateString
))
696 // '-99 23:12:40 GMT'
697 if (*dateString
!= '-' && *dateString
!= '/' && *dateString
!= ',' && !isASCIISpace(*dateString
))
703 if (month
< 0 || month
> 11)
707 if (year
<= 0 && *dateString
) {
708 year
= strtol(dateString
, &newPosStr
, 10);
713 // Don't fail if the time is missing.
718 dateString
= newPosStr
;
721 if (!(isASCIISpace(*newPosStr
) || *newPosStr
== ',')) {
722 if (*newPosStr
!= ':')
724 // There was no year; the number was the hour.
727 // in the normal case (we parsed the year), advance to the next number
728 dateString
= ++newPosStr
;
729 skipSpacesAndComments(dateString
);
732 hour
= strtol(dateString
, &newPosStr
, 10);
733 // Do not check for errno here since we want to continue
734 // even if errno was set becasue we are still looking
737 // Read a number? If not, this might be a timezone name.
738 if (newPosStr
!= dateString
) {
739 dateString
= newPosStr
;
741 if (hour
< 0 || hour
> 23)
748 if (*dateString
++ != ':')
751 minute
= strtol(dateString
, &newPosStr
, 10);
754 dateString
= newPosStr
;
756 if (minute
< 0 || minute
> 59)
760 if (*dateString
&& *dateString
!= ':' && !isASCIISpace(*dateString
))
763 // seconds are optional in rfc822 + rfc2822
764 if (*dateString
==':') {
767 second
= strtol(dateString
, &newPosStr
, 10);
770 dateString
= newPosStr
;
772 if (second
< 0 || second
> 59)
776 skipSpacesAndComments(dateString
);
778 if (strncasecmp(dateString
, "AM", 2) == 0) {
784 skipSpacesAndComments(dateString
);
785 } else if (strncasecmp(dateString
, "PM", 2) == 0) {
791 skipSpacesAndComments(dateString
);
799 // Don't fail if the time zone is missing.
800 // Some websites omit the time zone (4275206).
802 if (strncasecmp(dateString
, "GMT", 3) == 0 || strncasecmp(dateString
, "UTC", 3) == 0) {
807 if (*dateString
== '+' || *dateString
== '-') {
808 long o
= strtol(dateString
, &newPosStr
, 10);
811 dateString
= newPosStr
;
813 if (o
< -9959 || o
> 9959)
816 int sgn
= (o
< 0) ? -1 : 1;
818 if (*dateString
!= ':') {
819 offset
= ((o
/ 100) * 60 + (o
% 100)) * sgn
;
820 } else { // GMT+05:00
821 long o2
= strtol(dateString
, &newPosStr
, 10);
824 dateString
= newPosStr
;
825 offset
= (o
* 60 + o2
) * sgn
;
829 for (int i
= 0; i
< int(sizeof(known_zones
) / sizeof(KnownZone
)); i
++) {
830 if (0 == strncasecmp(dateString
, known_zones
[i
].tzName
, strlen(known_zones
[i
].tzName
))) {
831 offset
= known_zones
[i
].tzOffset
;
832 dateString
+= strlen(known_zones
[i
].tzName
);
840 skipSpacesAndComments(dateString
);
842 if (*dateString
&& year
== -1) {
843 year
= strtol(dateString
, &newPosStr
, 10);
846 dateString
= newPosStr
;
849 skipSpacesAndComments(dateString
);
855 // Y2K: Handle 2 digit years.
856 if (year
>= 0 && year
< 100) {
863 // fall back to local timezone
866 memset(&t
, 0, sizeof(tm
));
869 t
.year
= year
- 1900;
875 // Use our gregorianDateTimeToMS() rather than mktime() as the latter can't handle the full year range.
876 return gregorianDateTimeToMS(t
, 0, false);
879 return (ymdhmsToSeconds(year
, month
+ 1, day
, hour
, minute
, second
) - (offset
* 60.0)) * msPerSecond
;
882 double timeClip(double t
)
886 if (fabs(t
) > 8.64E15
)
893 JSValue
* dateProtoFuncToString(ExecState
* exec
, JSObject
* thisObj
, const List
&)
895 if (!thisObj
->inherits(&DateInstance::info
))
896 return throwError(exec
, TypeError
);
898 const bool utc
= false;
900 DateInstance
* thisDateObj
= static_cast<DateInstance
*>(thisObj
);
901 JSValue
* v
= thisDateObj
->internalValue();
902 double milli
= v
->toNumber(exec
);
904 return jsString("Invalid Date");
907 msToGregorianDateTime(milli
, utc
, t
);
908 return jsString(formatDate(t
) + " " + formatTime(t
, utc
));
911 JSValue
* dateProtoFuncToUTCString(ExecState
* exec
, JSObject
* thisObj
, const List
&)
913 if (!thisObj
->inherits(&DateInstance::info
))
914 return throwError(exec
, TypeError
);
916 const bool utc
= true;
918 DateInstance
* thisDateObj
= static_cast<DateInstance
*>(thisObj
);
919 JSValue
* v
= thisDateObj
->internalValue();
920 double milli
= v
->toNumber(exec
);
922 return jsString("Invalid Date");
925 msToGregorianDateTime(milli
, utc
, t
);
926 return jsString(formatDateUTCVariant(t
) + " " + formatTime(t
, utc
));
929 JSValue
* dateProtoFuncToDateString(ExecState
* exec
, JSObject
* thisObj
, const List
&)
931 if (!thisObj
->inherits(&DateInstance::info
))
932 return throwError(exec
, TypeError
);
934 const bool utc
= false;
936 DateInstance
* thisDateObj
= static_cast<DateInstance
*>(thisObj
);
937 JSValue
* v
= thisDateObj
->internalValue();
938 double milli
= v
->toNumber(exec
);
940 return jsString("Invalid Date");
943 msToGregorianDateTime(milli
, utc
, t
);
944 return jsString(formatDate(t
));
947 JSValue
* dateProtoFuncToTimeString(ExecState
* exec
, JSObject
* thisObj
, const List
&)
949 if (!thisObj
->inherits(&DateInstance::info
))
950 return throwError(exec
, TypeError
);
952 const bool utc
= false;
954 DateInstance
* thisDateObj
= static_cast<DateInstance
*>(thisObj
);
955 JSValue
* v
= thisDateObj
->internalValue();
956 double milli
= v
->toNumber(exec
);
958 return jsString("Invalid Date");
961 msToGregorianDateTime(milli
, utc
, t
);
962 return jsString(formatTime(t
, utc
));
965 JSValue
* dateProtoFuncToLocaleString(ExecState
* exec
, JSObject
* thisObj
, const List
& args
)
967 if (!thisObj
->inherits(&DateInstance::info
))
968 return throwError(exec
, TypeError
);
970 DateInstance
* thisDateObj
= static_cast<DateInstance
*>(thisObj
);
971 JSValue
* v
= thisDateObj
->internalValue();
972 double milli
= v
->toNumber(exec
);
974 return jsString("Invalid Date");
976 double secs
= floor(milli
/ msPerSecond
);
977 return jsString(formatLocaleDate(exec
, secs
, true, true, args
));
980 JSValue
* dateProtoFuncToLocaleDateString(ExecState
* exec
, JSObject
* thisObj
, const List
& args
)
982 if (!thisObj
->inherits(&DateInstance::info
))
983 return throwError(exec
, TypeError
);
985 DateInstance
* thisDateObj
= static_cast<DateInstance
*>(thisObj
);
986 JSValue
* v
= thisDateObj
->internalValue();
987 double milli
= v
->toNumber(exec
);
989 return jsString("Invalid Date");
991 double secs
= floor(milli
/ msPerSecond
);
992 return jsString(formatLocaleDate(exec
, secs
, true, false, args
));
995 JSValue
* dateProtoFuncToLocaleTimeString(ExecState
* exec
, JSObject
* thisObj
, const List
& args
)
997 if (!thisObj
->inherits(&DateInstance::info
))
998 return throwError(exec
, TypeError
);
1000 DateInstance
* thisDateObj
= static_cast<DateInstance
*>(thisObj
);
1001 JSValue
* v
= thisDateObj
->internalValue();
1002 double milli
= v
->toNumber(exec
);
1004 return jsString("Invalid Date");
1006 double secs
= floor(milli
/ msPerSecond
);
1007 return jsString(formatLocaleDate(exec
, secs
, false, true, args
));
1010 JSValue
* dateProtoFuncValueOf(ExecState
* exec
, JSObject
* thisObj
, const List
&)
1012 if (!thisObj
->inherits(&DateInstance::info
))
1013 return throwError(exec
, TypeError
);
1015 DateInstance
* thisDateObj
= static_cast<DateInstance
*>(thisObj
);
1016 JSValue
* v
= thisDateObj
->internalValue();
1017 double milli
= v
->toNumber(exec
);
1021 return jsNumber(milli
);
1024 JSValue
* dateProtoFuncGetTime(ExecState
* exec
, JSObject
* thisObj
, const List
&)
1026 if (!thisObj
->inherits(&DateInstance::info
))
1027 return throwError(exec
, TypeError
);
1029 DateInstance
* thisDateObj
= static_cast<DateInstance
*>(thisObj
);
1030 JSValue
* v
= thisDateObj
->internalValue();
1031 double milli
= v
->toNumber(exec
);
1035 return jsNumber(milli
);
1038 JSValue
* dateProtoFuncGetFullYear(ExecState
* exec
, JSObject
* thisObj
, const List
&)
1040 if (!thisObj
->inherits(&DateInstance::info
))
1041 return throwError(exec
, TypeError
);
1043 const bool utc
= false;
1045 DateInstance
* thisDateObj
= static_cast<DateInstance
*>(thisObj
);
1046 JSValue
* v
= thisDateObj
->internalValue();
1047 double milli
= v
->toNumber(exec
);
1051 GregorianDateTime t
;
1052 msToGregorianDateTime(milli
, utc
, t
);
1053 return jsNumber(1900 + t
.year
);
1056 JSValue
* dateProtoFuncGetUTCFullYear(ExecState
* exec
, JSObject
* thisObj
, const List
&)
1058 if (!thisObj
->inherits(&DateInstance::info
))
1059 return throwError(exec
, TypeError
);
1061 const bool utc
= true;
1063 DateInstance
* thisDateObj
= static_cast<DateInstance
*>(thisObj
);
1064 JSValue
* v
= thisDateObj
->internalValue();
1065 double milli
= v
->toNumber(exec
);
1069 GregorianDateTime t
;
1070 msToGregorianDateTime(milli
, utc
, t
);
1071 return jsNumber(1900 + t
.year
);
1074 JSValue
* dateProtoFuncToGMTString(ExecState
* exec
, JSObject
* thisObj
, const List
&)
1076 if (!thisObj
->inherits(&DateInstance::info
))
1077 return throwError(exec
, TypeError
);
1079 const bool utc
= true;
1081 DateInstance
* thisDateObj
= static_cast<DateInstance
*>(thisObj
);
1082 JSValue
* v
= thisDateObj
->internalValue();
1083 double milli
= v
->toNumber(exec
);
1085 return jsString("Invalid Date");
1087 GregorianDateTime t
;
1088 msToGregorianDateTime(milli
, utc
, t
);
1089 return jsString(formatDateUTCVariant(t
) + " " + formatTime(t
, utc
));
1092 JSValue
* dateProtoFuncGetMonth(ExecState
* exec
, JSObject
* thisObj
, const List
&)
1094 if (!thisObj
->inherits(&DateInstance::info
))
1095 return throwError(exec
, TypeError
);
1097 const bool utc
= false;
1099 DateInstance
* thisDateObj
= static_cast<DateInstance
*>(thisObj
);
1100 JSValue
* v
= thisDateObj
->internalValue();
1101 double milli
= v
->toNumber(exec
);
1105 GregorianDateTime t
;
1106 msToGregorianDateTime(milli
, utc
, t
);
1107 return jsNumber(t
.month
);
1110 JSValue
* dateProtoFuncGetUTCMonth(ExecState
* exec
, JSObject
* thisObj
, const List
&)
1112 if (!thisObj
->inherits(&DateInstance::info
))
1113 return throwError(exec
, TypeError
);
1115 const bool utc
= true;
1117 DateInstance
* thisDateObj
= static_cast<DateInstance
*>(thisObj
);
1118 JSValue
* v
= thisDateObj
->internalValue();
1119 double milli
= v
->toNumber(exec
);
1123 GregorianDateTime t
;
1124 msToGregorianDateTime(milli
, utc
, t
);
1125 return jsNumber(t
.month
);
1128 JSValue
* dateProtoFuncGetDate(ExecState
* exec
, JSObject
* thisObj
, const List
&)
1130 if (!thisObj
->inherits(&DateInstance::info
))
1131 return throwError(exec
, TypeError
);
1133 const bool utc
= false;
1135 DateInstance
* thisDateObj
= static_cast<DateInstance
*>(thisObj
);
1136 JSValue
* v
= thisDateObj
->internalValue();
1137 double milli
= v
->toNumber(exec
);
1141 GregorianDateTime t
;
1142 msToGregorianDateTime(milli
, utc
, t
);
1143 return jsNumber(t
.monthDay
);
1146 JSValue
* dateProtoFuncGetUTCDate(ExecState
* exec
, JSObject
* thisObj
, const List
&)
1148 if (!thisObj
->inherits(&DateInstance::info
))
1149 return throwError(exec
, TypeError
);
1151 const bool utc
= true;
1153 DateInstance
* thisDateObj
= static_cast<DateInstance
*>(thisObj
);
1154 JSValue
* v
= thisDateObj
->internalValue();
1155 double milli
= v
->toNumber(exec
);
1159 GregorianDateTime t
;
1160 msToGregorianDateTime(milli
, utc
, t
);
1161 return jsNumber(t
.monthDay
);
1164 JSValue
* dateProtoFuncGetDay(ExecState
* exec
, JSObject
* thisObj
, const List
&)
1166 if (!thisObj
->inherits(&DateInstance::info
))
1167 return throwError(exec
, TypeError
);
1169 const bool utc
= false;
1171 DateInstance
* thisDateObj
= static_cast<DateInstance
*>(thisObj
);
1172 JSValue
* v
= thisDateObj
->internalValue();
1173 double milli
= v
->toNumber(exec
);
1177 GregorianDateTime t
;
1178 msToGregorianDateTime(milli
, utc
, t
);
1179 return jsNumber(t
.weekDay
);
1182 JSValue
* dateProtoFuncGetUTCDay(ExecState
* exec
, JSObject
* thisObj
, const List
&)
1184 if (!thisObj
->inherits(&DateInstance::info
))
1185 return throwError(exec
, TypeError
);
1187 const bool utc
= true;
1189 DateInstance
* thisDateObj
= static_cast<DateInstance
*>(thisObj
);
1190 JSValue
* v
= thisDateObj
->internalValue();
1191 double milli
= v
->toNumber(exec
);
1195 GregorianDateTime t
;
1196 msToGregorianDateTime(milli
, utc
, t
);
1197 return jsNumber(t
.weekDay
);
1200 JSValue
* dateProtoFuncGetHours(ExecState
* exec
, JSObject
* thisObj
, const List
&)
1202 if (!thisObj
->inherits(&DateInstance::info
))
1203 return throwError(exec
, TypeError
);
1205 const bool utc
= false;
1207 DateInstance
* thisDateObj
= static_cast<DateInstance
*>(thisObj
);
1208 JSValue
* v
= thisDateObj
->internalValue();
1209 double milli
= v
->toNumber(exec
);
1213 GregorianDateTime t
;
1214 msToGregorianDateTime(milli
, utc
, t
);
1215 return jsNumber(t
.hour
);
1218 JSValue
* dateProtoFuncGetUTCHours(ExecState
* exec
, JSObject
* thisObj
, const List
&)
1220 if (!thisObj
->inherits(&DateInstance::info
))
1221 return throwError(exec
, TypeError
);
1223 const bool utc
= true;
1225 DateInstance
* thisDateObj
= static_cast<DateInstance
*>(thisObj
);
1226 JSValue
* v
= thisDateObj
->internalValue();
1227 double milli
= v
->toNumber(exec
);
1231 GregorianDateTime t
;
1232 msToGregorianDateTime(milli
, utc
, t
);
1233 return jsNumber(t
.hour
);
1236 JSValue
* dateProtoFuncGetMinutes(ExecState
* exec
, JSObject
* thisObj
, const List
&)
1238 if (!thisObj
->inherits(&DateInstance::info
))
1239 return throwError(exec
, TypeError
);
1241 const bool utc
= false;
1243 DateInstance
* thisDateObj
= static_cast<DateInstance
*>(thisObj
);
1244 JSValue
* v
= thisDateObj
->internalValue();
1245 double milli
= v
->toNumber(exec
);
1249 GregorianDateTime t
;
1250 msToGregorianDateTime(milli
, utc
, t
);
1251 return jsNumber(t
.minute
);
1254 JSValue
* dateProtoFuncGetUTCMinutes(ExecState
* exec
, JSObject
* thisObj
, const List
&)
1256 if (!thisObj
->inherits(&DateInstance::info
))
1257 return throwError(exec
, TypeError
);
1259 const bool utc
= true;
1261 DateInstance
* thisDateObj
= static_cast<DateInstance
*>(thisObj
);
1262 JSValue
* v
= thisDateObj
->internalValue();
1263 double milli
= v
->toNumber(exec
);
1267 GregorianDateTime t
;
1268 msToGregorianDateTime(milli
, utc
, t
);
1269 return jsNumber(t
.minute
);
1272 JSValue
* dateProtoFuncGetSeconds(ExecState
* exec
, JSObject
* thisObj
, const List
&)
1274 if (!thisObj
->inherits(&DateInstance::info
))
1275 return throwError(exec
, TypeError
);
1277 const bool utc
= false;
1279 DateInstance
* thisDateObj
= static_cast<DateInstance
*>(thisObj
);
1280 JSValue
* v
= thisDateObj
->internalValue();
1281 double milli
= v
->toNumber(exec
);
1285 GregorianDateTime t
;
1286 msToGregorianDateTime(milli
, utc
, t
);
1287 return jsNumber(t
.second
);
1290 JSValue
* dateProtoFuncGetUTCSeconds(ExecState
* exec
, JSObject
* thisObj
, const List
&)
1292 if (!thisObj
->inherits(&DateInstance::info
))
1293 return throwError(exec
, TypeError
);
1295 const bool utc
= true;
1297 DateInstance
* thisDateObj
= static_cast<DateInstance
*>(thisObj
);
1298 JSValue
* v
= thisDateObj
->internalValue();
1299 double milli
= v
->toNumber(exec
);
1303 GregorianDateTime t
;
1304 msToGregorianDateTime(milli
, utc
, t
);
1305 return jsNumber(t
.second
);
1308 JSValue
* dateProtoFuncGetMilliSeconds(ExecState
* exec
, JSObject
* thisObj
, const List
&)
1310 if (!thisObj
->inherits(&DateInstance::info
))
1311 return throwError(exec
, TypeError
);
1313 DateInstance
* thisDateObj
= static_cast<DateInstance
*>(thisObj
);
1314 JSValue
* v
= thisDateObj
->internalValue();
1315 double milli
= v
->toNumber(exec
);
1319 double secs
= floor(milli
/ msPerSecond
);
1320 double ms
= milli
- secs
* msPerSecond
;
1321 return jsNumber(ms
);
1324 JSValue
* dateProtoFuncGetUTCMilliseconds(ExecState
* exec
, JSObject
* thisObj
, const List
&)
1326 if (!thisObj
->inherits(&DateInstance::info
))
1327 return throwError(exec
, TypeError
);
1329 DateInstance
* thisDateObj
= static_cast<DateInstance
*>(thisObj
);
1330 JSValue
* v
= thisDateObj
->internalValue();
1331 double milli
= v
->toNumber(exec
);
1335 double secs
= floor(milli
/ msPerSecond
);
1336 double ms
= milli
- secs
* msPerSecond
;
1337 return jsNumber(ms
);
1340 JSValue
* dateProtoFuncGetTimezoneOffset(ExecState
* exec
, JSObject
* thisObj
, const List
&)
1342 if (!thisObj
->inherits(&DateInstance::info
))
1343 return throwError(exec
, TypeError
);
1345 const bool utc
= false;
1347 DateInstance
* thisDateObj
= static_cast<DateInstance
*>(thisObj
);
1348 JSValue
* v
= thisDateObj
->internalValue();
1349 double milli
= v
->toNumber(exec
);
1353 GregorianDateTime t
;
1354 msToGregorianDateTime(milli
, utc
, t
);
1355 return jsNumber(-gmtoffset(t
) / minutesPerHour
);
1358 JSValue
* dateProtoFuncSetTime(ExecState
* exec
, JSObject
* thisObj
, const List
& args
)
1360 if (!thisObj
->inherits(&DateInstance::info
))
1361 return throwError(exec
, TypeError
);
1363 DateInstance
* thisDateObj
= static_cast<DateInstance
*>(thisObj
);
1365 double milli
= timeClip(args
[0]->toNumber(exec
));
1366 JSValue
* result
= jsNumber(milli
);
1367 thisDateObj
->setInternalValue(result
);
1371 static JSValue
* setNewValueFromTimeArgs(ExecState
* exec
, JSObject
* thisObj
, const List
& args
, int numArgsToUse
, bool inputIsUTC
)
1373 if (!thisObj
->inherits(&DateInstance::info
))
1374 return throwError(exec
, TypeError
);
1376 DateInstance
* thisDateObj
= static_cast<DateInstance
*>(thisObj
);
1377 JSValue
* v
= thisDateObj
->internalValue();
1378 double milli
= v
->toNumber(exec
);
1379 double secs
= floor(milli
/ msPerSecond
);
1380 double ms
= milli
- secs
* msPerSecond
;
1382 GregorianDateTime t
;
1383 msToGregorianDateTime(milli
, inputIsUTC
, t
);
1385 fillStructuresUsingTimeArgs(exec
, args
, numArgsToUse
, &ms
, &t
);
1387 JSValue
* result
= jsNumber(gregorianDateTimeToMS(t
, ms
, inputIsUTC
));
1388 thisDateObj
->setInternalValue(result
);
1392 static JSValue
* setNewValueFromDateArgs(ExecState
* exec
, JSObject
* thisObj
, const List
& args
, int numArgsToUse
, bool inputIsUTC
)
1394 if (!thisObj
->inherits(&DateInstance::info
))
1395 return throwError(exec
, TypeError
);
1397 DateInstance
* thisDateObj
= static_cast<DateInstance
*>(thisObj
);
1398 JSValue
* v
= thisDateObj
->internalValue();
1399 double milli
= v
->toNumber(exec
);
1400 double secs
= floor(milli
/ msPerSecond
);
1401 double ms
= milli
- secs
* msPerSecond
;
1403 GregorianDateTime t
;
1404 msToGregorianDateTime(milli
, inputIsUTC
, t
);
1406 fillStructuresUsingDateArgs(exec
, args
, numArgsToUse
, &ms
, &t
);
1408 JSValue
* result
= jsNumber(gregorianDateTimeToMS(t
, ms
, inputIsUTC
));
1409 thisDateObj
->setInternalValue(result
);
1413 JSValue
* dateProtoFuncSetMilliSeconds(ExecState
* exec
, JSObject
* thisObj
, const List
& args
)
1415 const bool inputIsUTC
= false;
1416 return setNewValueFromTimeArgs(exec
, thisObj
, args
, 1, inputIsUTC
);
1419 JSValue
* dateProtoFuncSetUTCMilliseconds(ExecState
* exec
, JSObject
* thisObj
, const List
& args
)
1421 const bool inputIsUTC
= true;
1422 return setNewValueFromTimeArgs(exec
, thisObj
, args
, 1, inputIsUTC
);
1425 JSValue
* dateProtoFuncSetSeconds(ExecState
* exec
, JSObject
* thisObj
, const List
& args
)
1427 const bool inputIsUTC
= false;
1428 return setNewValueFromTimeArgs(exec
, thisObj
, args
, 2, inputIsUTC
);
1431 JSValue
* dateProtoFuncSetUTCSeconds(ExecState
* exec
, JSObject
* thisObj
, const List
& args
)
1433 const bool inputIsUTC
= true;
1434 return setNewValueFromTimeArgs(exec
, thisObj
, args
, 2, inputIsUTC
);
1437 JSValue
* dateProtoFuncSetMinutes(ExecState
* exec
, JSObject
* thisObj
, const List
& args
)
1439 const bool inputIsUTC
= false;
1440 return setNewValueFromTimeArgs(exec
, thisObj
, args
, 3, inputIsUTC
);
1443 JSValue
* dateProtoFuncSetUTCMinutes(ExecState
* exec
, JSObject
* thisObj
, const List
& args
)
1445 const bool inputIsUTC
= true;
1446 return setNewValueFromTimeArgs(exec
, thisObj
, args
, 3, inputIsUTC
);
1449 JSValue
* dateProtoFuncSetHours(ExecState
* exec
, JSObject
* thisObj
, const List
& args
)
1451 const bool inputIsUTC
= false;
1452 return setNewValueFromTimeArgs(exec
, thisObj
, args
, 4, inputIsUTC
);
1455 JSValue
* dateProtoFuncSetUTCHours(ExecState
* exec
, JSObject
* thisObj
, const List
& args
)
1457 const bool inputIsUTC
= true;
1458 return setNewValueFromTimeArgs(exec
, thisObj
, args
, 4, inputIsUTC
);
1461 JSValue
* dateProtoFuncSetDate(ExecState
* exec
, JSObject
* thisObj
, const List
& args
)
1463 const bool inputIsUTC
= false;
1464 return setNewValueFromDateArgs(exec
, thisObj
, args
, 1, inputIsUTC
);
1467 JSValue
* dateProtoFuncSetUTCDate(ExecState
* exec
, JSObject
* thisObj
, const List
& args
)
1469 const bool inputIsUTC
= true;
1470 return setNewValueFromDateArgs(exec
, thisObj
, args
, 1, inputIsUTC
);
1473 JSValue
* dateProtoFuncSetMonth(ExecState
* exec
, JSObject
* thisObj
, const List
& args
)
1475 const bool inputIsUTC
= false;
1476 return setNewValueFromDateArgs(exec
, thisObj
, args
, 2, inputIsUTC
);
1479 JSValue
* dateProtoFuncSetUTCMonth(ExecState
* exec
, JSObject
* thisObj
, const List
& args
)
1481 const bool inputIsUTC
= true;
1482 return setNewValueFromDateArgs(exec
, thisObj
, args
, 2, inputIsUTC
);
1485 JSValue
* dateProtoFuncSetFullYear(ExecState
* exec
, JSObject
* thisObj
, const List
& args
)
1487 const bool inputIsUTC
= false;
1488 return setNewValueFromDateArgs(exec
, thisObj
, args
, 3, inputIsUTC
);
1491 JSValue
* dateProtoFuncSetUTCFullYear(ExecState
* exec
, JSObject
* thisObj
, const List
& args
)
1493 const bool inputIsUTC
= true;
1494 return setNewValueFromDateArgs(exec
, thisObj
, args
, 3, inputIsUTC
);
1497 JSValue
* dateProtoFuncSetYear(ExecState
* exec
, JSObject
* thisObj
, const List
& args
)
1499 if (!thisObj
->inherits(&DateInstance::info
))
1500 return throwError(exec
, TypeError
);
1502 const bool utc
= false;
1504 DateInstance
* thisDateObj
= static_cast<DateInstance
*>(thisObj
);
1505 JSValue
* v
= thisDateObj
->internalValue();
1506 double milli
= v
->toNumber(exec
);
1507 double secs
= floor(milli
/ msPerSecond
);
1508 double ms
= milli
- secs
* msPerSecond
;
1510 GregorianDateTime t
;
1511 msToGregorianDateTime(milli
, utc
, t
);
1513 t
.year
= (args
[0]->toInt32(exec
) > 99 || args
[0]->toInt32(exec
) < 0) ? args
[0]->toInt32(exec
) - 1900 : args
[0]->toInt32(exec
);
1515 JSValue
* result
= jsNumber(gregorianDateTimeToMS(t
, ms
, utc
));
1516 thisDateObj
->setInternalValue(result
);
1520 JSValue
* dateProtoFuncGetYear(ExecState
* exec
, JSObject
* thisObj
, const List
&)
1522 if (!thisObj
->inherits(&DateInstance::info
))
1523 return throwError(exec
, TypeError
);
1525 const bool utc
= false;
1527 DateInstance
* thisDateObj
= static_cast<DateInstance
*>(thisObj
);
1528 JSValue
* v
= thisDateObj
->internalValue();
1529 double milli
= v
->toNumber(exec
);
1533 GregorianDateTime t
;
1534 msToGregorianDateTime(milli
, utc
, t
);
1536 // IE returns the full year even in getYear.
1537 if (exec
->dynamicGlobalObject()->compatMode() == IECompat
)
1538 return jsNumber(1900 + t
.year
);
1539 return jsNumber(t
.year
);