blob: d0e24abc503eb21124a430dc981ed17fe767d010 [file] [log] [blame]
Andrei Popescu31002712010-02-23 13:46:05 +00001// Copyright 2006-2008 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28
29// This file relies on the fact that the following declarations have been made
30// in v8natives.js:
Ben Murdoch3ef787d2012-04-12 10:51:47 +010031// var $isFinite = GlobalIsFinite;
Andrei Popescu31002712010-02-23 13:46:05 +000032
33// -------------------------------------------------------------------
34
35// This file contains date support implemented in JavaScript.
36
Andrei Popescu31002712010-02-23 13:46:05 +000037// Keep reference to original values of some global properties. This
38// has the added benefit that the code in this file is isolated from
39// changes to these properties.
Ben Murdoch3ef787d2012-04-12 10:51:47 +010040var $Date = global.Date;
Andrei Popescu31002712010-02-23 13:46:05 +000041
42// Helper function to throw error.
43function ThrowDateTypeError() {
44 throw new $TypeError('this is not a Date object.');
45}
46
Andrei Popescu31002712010-02-23 13:46:05 +000047
48var timezone_cache_time = $NaN;
49var timezone_cache_timezone;
50
51function LocalTimezone(t) {
52 if (NUMBER_IS_NAN(t)) return "";
53 if (t == timezone_cache_time) {
54 return timezone_cache_timezone;
55 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010056 var timezone = %DateLocalTimezone(t);
Andrei Popescu31002712010-02-23 13:46:05 +000057 timezone_cache_time = t;
58 timezone_cache_timezone = timezone;
59 return timezone;
60}
61
62
Andrei Popescu31002712010-02-23 13:46:05 +000063function UTC(time) {
64 if (NUMBER_IS_NAN(time)) return time;
Andrei Popescu6599b9d2010-04-28 13:01:47 +010065 // local_time_offset is needed before the call to DaylightSavingsOffset,
66 // so it may be uninitialized.
Ben Murdoch3ef787d2012-04-12 10:51:47 +010067 return %DateToUTC(time);
Andrei Popescu31002712010-02-23 13:46:05 +000068}
69
70
71// ECMA 262 - 15.9.1.11
72function MakeTime(hour, min, sec, ms) {
73 if (!$isFinite(hour)) return $NaN;
74 if (!$isFinite(min)) return $NaN;
75 if (!$isFinite(sec)) return $NaN;
76 if (!$isFinite(ms)) return $NaN;
77 return TO_INTEGER(hour) * msPerHour
78 + TO_INTEGER(min) * msPerMinute
79 + TO_INTEGER(sec) * msPerSecond
80 + TO_INTEGER(ms);
81}
82
83
84// ECMA 262 - 15.9.1.12
85function TimeInYear(year) {
86 return DaysInYear(year) * msPerDay;
87}
88
89
Andrei Popescu31002712010-02-23 13:46:05 +000090// Compute number of days given a year, month, date.
91// Note that month and date can lie outside the normal range.
92// For example:
93// MakeDay(2007, -4, 20) --> MakeDay(2006, 8, 20)
94// MakeDay(2007, -33, 1) --> MakeDay(2004, 3, 1)
95// MakeDay(2007, 14, -50) --> MakeDay(2007, 8, 11)
96function MakeDay(year, month, date) {
97 if (!$isFinite(year) || !$isFinite(month) || !$isFinite(date)) return $NaN;
98
Steve Block8defd9f2010-07-08 12:39:36 +010099 // Convert to integer and map -0 to 0.
100 year = TO_INTEGER_MAP_MINUS_ZERO(year);
101 month = TO_INTEGER_MAP_MINUS_ZERO(month);
102 date = TO_INTEGER_MAP_MINUS_ZERO(date);
Andrei Popescu31002712010-02-23 13:46:05 +0000103
Steve Block6ded16b2010-05-10 14:33:55 +0100104 if (year < kMinYear || year > kMaxYear ||
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100105 month < kMinMonth || month > kMaxMonth) {
Steve Block6ded16b2010-05-10 14:33:55 +0100106 return $NaN;
Andrei Popescu31002712010-02-23 13:46:05 +0000107 }
108
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100109 // Now we rely on year and month being SMIs.
110 return %DateMakeDay(year, month) + date - 1;
Andrei Popescu31002712010-02-23 13:46:05 +0000111}
112
113
114// ECMA 262 - 15.9.1.13
115function MakeDate(day, time) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100116 var time = day * msPerDay + time;
117 // Some of our runtime funtions for computing UTC(time) rely on
118 // times not being significantly larger than MAX_TIME_MS. If there
119 // is no way that the time can be within range even after UTC
120 // conversion we return NaN immediately instead of relying on
121 // TimeClip to do it.
122 if ($abs(time) > MAX_TIME_BEFORE_UTC) return $NaN;
123 return time;
Andrei Popescu31002712010-02-23 13:46:05 +0000124}
125
126
127// ECMA 262 - 15.9.1.14
128function TimeClip(time) {
129 if (!$isFinite(time)) return $NaN;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100130 if ($abs(time) > MAX_TIME_MS) return $NaN;
Andrei Popescu31002712010-02-23 13:46:05 +0000131 return TO_INTEGER(time);
132}
133
134
135// The Date cache is used to limit the cost of parsing the same Date
136// strings over and over again.
137var Date_cache = {
138 // Cached time value.
139 time: $NaN,
Andrei Popescu31002712010-02-23 13:46:05 +0000140 // String input for which the cached time is valid.
141 string: null
142};
143
144
145%SetCode($Date, function(year, month, date, hours, minutes, seconds, ms) {
146 if (!%_IsConstructCall()) {
147 // ECMA 262 - 15.9.2
148 return (new $Date()).toString();
149 }
150
151 // ECMA 262 - 15.9.3
152 var argc = %_ArgumentsLength();
153 var value;
154 if (argc == 0) {
155 value = %DateCurrentTime();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100156 SET_UTC_DATE_VALUE(this, value);
Andrei Popescu31002712010-02-23 13:46:05 +0000157 } else if (argc == 1) {
158 if (IS_NUMBER(year)) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100159 value = year;
Andrei Popescu31002712010-02-23 13:46:05 +0000160 } else if (IS_STRING(year)) {
161 // Probe the Date cache. If we already have a time value for the
162 // given time, we re-use that instead of parsing the string again.
163 var cache = Date_cache;
164 if (cache.string === year) {
165 value = cache.time;
166 } else {
167 value = DateParse(year);
168 if (!NUMBER_IS_NAN(value)) {
169 cache.time = value;
Andrei Popescu31002712010-02-23 13:46:05 +0000170 cache.string = year;
171 }
172 }
173
174 } else {
175 // According to ECMA 262, no hint should be given for this
176 // conversion. However, ToPrimitive defaults to STRING_HINT for
177 // Date objects which will lose precision when the Date
178 // constructor is called with another Date object as its
179 // argument. We therefore use NUMBER_HINT for the conversion,
180 // which is the default for everything else than Date objects.
181 // This makes us behave like KJS and SpiderMonkey.
182 var time = ToPrimitive(year, NUMBER_HINT);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100183 value = IS_STRING(time) ? DateParse(time) : ToNumber(time);
Andrei Popescu31002712010-02-23 13:46:05 +0000184 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100185 SET_UTC_DATE_VALUE(this, value);
Andrei Popescu31002712010-02-23 13:46:05 +0000186 } else {
187 year = ToNumber(year);
188 month = ToNumber(month);
189 date = argc > 2 ? ToNumber(date) : 1;
190 hours = argc > 3 ? ToNumber(hours) : 0;
191 minutes = argc > 4 ? ToNumber(minutes) : 0;
192 seconds = argc > 5 ? ToNumber(seconds) : 0;
193 ms = argc > 6 ? ToNumber(ms) : 0;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100194 year = (!NUMBER_IS_NAN(year) &&
195 0 <= TO_INTEGER(year) &&
196 TO_INTEGER(year) <= 99) ? 1900 + TO_INTEGER(year) : year;
Andrei Popescu31002712010-02-23 13:46:05 +0000197 var day = MakeDay(year, month, date);
198 var time = MakeTime(hours, minutes, seconds, ms);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100199 value = MakeDate(day, time);
200 SET_LOCAL_DATE_VALUE(this, value);
Andrei Popescu31002712010-02-23 13:46:05 +0000201 }
Andrei Popescu31002712010-02-23 13:46:05 +0000202});
203
204
Andrei Popescu31002712010-02-23 13:46:05 +0000205%FunctionSetPrototype($Date, new $Date($NaN));
206
207
208var WeekDays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100209var Months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
210 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
Andrei Popescu31002712010-02-23 13:46:05 +0000211
212
213function TwoDigitString(value) {
214 return value < 10 ? "0" + value : "" + value;
215}
216
217
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100218function DateString(date) {
219 return WeekDays[LOCAL_WEEKDAY(date)] + ' '
220 + Months[LOCAL_MONTH(date)] + ' '
221 + TwoDigitString(LOCAL_DAY(date)) + ' '
222 + LOCAL_YEAR(date);
Andrei Popescu31002712010-02-23 13:46:05 +0000223}
224
225
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100226var LongWeekDays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday',
227 'Thursday', 'Friday', 'Saturday'];
228var LongMonths = ['January', 'February', 'March', 'April', 'May', 'June',
229 'July', 'August', 'September', 'October', 'November', 'December'];
Andrei Popescu31002712010-02-23 13:46:05 +0000230
231
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100232function LongDateString(date) {
233 return LongWeekDays[LOCAL_WEEKDAY(date)] + ', '
234 + LongMonths[LOCAL_MONTH(date)] + ' '
235 + TwoDigitString(LOCAL_DAY(date)) + ', '
236 + LOCAL_YEAR(date);
Andrei Popescu31002712010-02-23 13:46:05 +0000237}
238
239
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100240function TimeString(date) {
241 return TwoDigitString(LOCAL_HOUR(date)) + ':'
242 + TwoDigitString(LOCAL_MIN(date)) + ':'
243 + TwoDigitString(LOCAL_SEC(date));
Andrei Popescu31002712010-02-23 13:46:05 +0000244}
245
246
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100247function TimeStringUTC(date) {
248 return TwoDigitString(UTC_HOUR(date)) + ':'
249 + TwoDigitString(UTC_MIN(date)) + ':'
250 + TwoDigitString(UTC_SEC(date));
251}
Ben Murdochd69d2e32010-03-30 12:55:27 +0100252
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100253
254function LocalTimezoneString(date) {
255 var timezone = LocalTimezone(UTC_DATE_VALUE(date));
256
257 var timezoneOffset = -TIMEZONE_OFFSET(date);
Andrei Popescu31002712010-02-23 13:46:05 +0000258 var sign = (timezoneOffset >= 0) ? 1 : -1;
259 var hours = FLOOR((sign * timezoneOffset)/60);
260 var min = FLOOR((sign * timezoneOffset)%60);
261 var gmt = ' GMT' + ((sign == 1) ? '+' : '-') +
262 TwoDigitString(hours) + TwoDigitString(min);
Ben Murdochd69d2e32010-03-30 12:55:27 +0100263 return gmt + ' (' + timezone + ')';
Andrei Popescu31002712010-02-23 13:46:05 +0000264}
265
266
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100267function DatePrintString(date) {
268 return DateString(date) + ' ' + TimeString(date);
Andrei Popescu31002712010-02-23 13:46:05 +0000269}
270
271// -------------------------------------------------------------------
272
273// Reused output buffer. Used when parsing date strings.
Steve Block6ded16b2010-05-10 14:33:55 +0100274var parse_buffer = $Array(8);
Andrei Popescu31002712010-02-23 13:46:05 +0000275
276// ECMA 262 - 15.9.4.2
277function DateParse(string) {
278 var arr = %DateParseString(ToString(string), parse_buffer);
279 if (IS_NULL(arr)) return $NaN;
280
281 var day = MakeDay(arr[0], arr[1], arr[2]);
Steve Block6ded16b2010-05-10 14:33:55 +0100282 var time = MakeTime(arr[3], arr[4], arr[5], arr[6]);
Andrei Popescu31002712010-02-23 13:46:05 +0000283 var date = MakeDate(day, time);
284
Steve Block6ded16b2010-05-10 14:33:55 +0100285 if (IS_NULL(arr[7])) {
Andrei Popescu31002712010-02-23 13:46:05 +0000286 return TimeClip(UTC(date));
287 } else {
Steve Block6ded16b2010-05-10 14:33:55 +0100288 return TimeClip(date - arr[7] * 1000);
Andrei Popescu31002712010-02-23 13:46:05 +0000289 }
290}
291
292
293// ECMA 262 - 15.9.4.3
294function DateUTC(year, month, date, hours, minutes, seconds, ms) {
295 year = ToNumber(year);
296 month = ToNumber(month);
297 var argc = %_ArgumentsLength();
298 date = argc > 2 ? ToNumber(date) : 1;
299 hours = argc > 3 ? ToNumber(hours) : 0;
300 minutes = argc > 4 ? ToNumber(minutes) : 0;
301 seconds = argc > 5 ? ToNumber(seconds) : 0;
302 ms = argc > 6 ? ToNumber(ms) : 0;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100303 year = (!NUMBER_IS_NAN(year) &&
304 0 <= TO_INTEGER(year) &&
305 TO_INTEGER(year) <= 99) ? 1900 + TO_INTEGER(year) : year;
Andrei Popescu31002712010-02-23 13:46:05 +0000306 var day = MakeDay(year, month, date);
307 var time = MakeTime(hours, minutes, seconds, ms);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100308 return TimeClip(MakeDate(day, time));
Andrei Popescu31002712010-02-23 13:46:05 +0000309}
310
311
312// Mozilla-specific extension. Returns the number of milliseconds
313// elapsed since 1 January 1970 00:00:00 UTC.
314function DateNow() {
315 return %DateCurrentTime();
316}
317
318
319// ECMA 262 - 15.9.5.2
320function DateToString() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100321 CHECK_DATE(this);
322 var t = UTC_DATE_VALUE(this)
Andrei Popescu31002712010-02-23 13:46:05 +0000323 if (NUMBER_IS_NAN(t)) return kInvalidDate;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100324 var time_zone_string = LocalTimezoneString(this)
325 return DatePrintString(this) + time_zone_string;
Andrei Popescu31002712010-02-23 13:46:05 +0000326}
327
328
329// ECMA 262 - 15.9.5.3
330function DateToDateString() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100331 CHECK_DATE(this);
332 var t = UTC_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000333 if (NUMBER_IS_NAN(t)) return kInvalidDate;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100334 return DateString(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000335}
336
337
338// ECMA 262 - 15.9.5.4
339function DateToTimeString() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100340 CHECK_DATE(this);
341 var t = UTC_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000342 if (NUMBER_IS_NAN(t)) return kInvalidDate;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100343 var time_zone_string = LocalTimezoneString(this);
344 return TimeString(this) + time_zone_string;
Andrei Popescu31002712010-02-23 13:46:05 +0000345}
346
347
348// ECMA 262 - 15.9.5.5
349function DateToLocaleString() {
Steve Block1e0659c2011-05-24 12:43:12 +0100350 return %_CallFunction(this, DateToString);
Andrei Popescu31002712010-02-23 13:46:05 +0000351}
352
353
354// ECMA 262 - 15.9.5.6
355function DateToLocaleDateString() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100356 CHECK_DATE(this);
357 var t = UTC_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000358 if (NUMBER_IS_NAN(t)) return kInvalidDate;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100359 return LongDateString(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000360}
361
362
363// ECMA 262 - 15.9.5.7
364function DateToLocaleTimeString() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100365 CHECK_DATE(this);
366 var t = UTC_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000367 if (NUMBER_IS_NAN(t)) return kInvalidDate;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100368 return TimeString(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000369}
370
371
372// ECMA 262 - 15.9.5.8
373function DateValueOf() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100374 CHECK_DATE(this);
375 return UTC_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000376}
377
378
379// ECMA 262 - 15.9.5.9
Andrei Popescu402d9372010-02-26 13:31:12 +0000380function DateGetTime() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100381 CHECK_DATE(this);
382 return UTC_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000383}
384
385
386// ECMA 262 - 15.9.5.10
387function DateGetFullYear() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100388 CHECK_DATE(this);
389 return LOCAL_YEAR(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000390}
391
392
393// ECMA 262 - 15.9.5.11
394function DateGetUTCFullYear() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100395 CHECK_DATE(this);
396 return UTC_YEAR(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000397}
398
399
400// ECMA 262 - 15.9.5.12
401function DateGetMonth() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100402 CHECK_DATE(this);
403 return LOCAL_MONTH(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000404}
405
406
407// ECMA 262 - 15.9.5.13
408function DateGetUTCMonth() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100409 CHECK_DATE(this);
410 return UTC_MONTH(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000411}
412
413
414// ECMA 262 - 15.9.5.14
415function DateGetDate() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100416 CHECK_DATE(this);
417 return LOCAL_DAY(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000418}
419
420
421// ECMA 262 - 15.9.5.15
422function DateGetUTCDate() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100423 CHECK_DATE(this);
424 return UTC_DAY(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000425}
426
427
428// ECMA 262 - 15.9.5.16
429function DateGetDay() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100430 CHECK_DATE(this);
431 return LOCAL_WEEKDAY(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000432}
433
434
435// ECMA 262 - 15.9.5.17
436function DateGetUTCDay() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100437 CHECK_DATE(this);
438 return UTC_WEEKDAY(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000439}
440
441
442// ECMA 262 - 15.9.5.18
443function DateGetHours() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100444 CHECK_DATE(this);
445 return LOCAL_HOUR(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000446}
447
448
449// ECMA 262 - 15.9.5.19
450function DateGetUTCHours() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100451 CHECK_DATE(this);
452 return UTC_HOUR(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000453}
454
455
456// ECMA 262 - 15.9.5.20
457function DateGetMinutes() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100458 CHECK_DATE(this);
459 return LOCAL_MIN(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000460}
461
462
463// ECMA 262 - 15.9.5.21
464function DateGetUTCMinutes() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100465 CHECK_DATE(this);
466 return UTC_MIN(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000467}
468
469
470// ECMA 262 - 15.9.5.22
471function DateGetSeconds() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100472 CHECK_DATE(this);
473 return LOCAL_SEC(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000474}
475
476
477// ECMA 262 - 15.9.5.23
478function DateGetUTCSeconds() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100479 CHECK_DATE(this);
480 return UTC_SEC(this)
Andrei Popescu31002712010-02-23 13:46:05 +0000481}
482
483
484// ECMA 262 - 15.9.5.24
485function DateGetMilliseconds() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100486 CHECK_DATE(this);
487 return LOCAL_MS(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000488}
489
490
491// ECMA 262 - 15.9.5.25
492function DateGetUTCMilliseconds() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100493 CHECK_DATE(this);
494 return UTC_MS(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000495}
496
497
498// ECMA 262 - 15.9.5.26
499function DateGetTimezoneOffset() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100500 CHECK_DATE(this);
501 return TIMEZONE_OFFSET(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000502}
503
504
505// ECMA 262 - 15.9.5.27
506function DateSetTime(ms) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100507 CHECK_DATE(this);
508 SET_UTC_DATE_VALUE(this, ToNumber(ms));
509 return UTC_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000510}
511
512
513// ECMA 262 - 15.9.5.28
514function DateSetMilliseconds(ms) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100515 CHECK_DATE(this);
516 var t = LOCAL_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000517 ms = ToNumber(ms);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100518 var time = MakeTime(LOCAL_HOUR(this), LOCAL_MIN(this), LOCAL_SEC(this), ms);
Ben Murdoch84774f42012-05-17 10:59:30 +0100519 return SET_LOCAL_DATE_VALUE(this, MakeDate(LOCAL_DAYS(this), time));
Andrei Popescu31002712010-02-23 13:46:05 +0000520}
521
522
523// ECMA 262 - 15.9.5.29
524function DateSetUTCMilliseconds(ms) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100525 CHECK_DATE(this);
526 var t = UTC_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000527 ms = ToNumber(ms);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100528 var time = MakeTime(UTC_HOUR(this),
529 UTC_MIN(this),
530 UTC_SEC(this),
531 ms);
532 return SET_UTC_DATE_VALUE(this, MakeDate(UTC_DAYS(this), time));
Andrei Popescu31002712010-02-23 13:46:05 +0000533}
534
535
536// ECMA 262 - 15.9.5.30
537function DateSetSeconds(sec, ms) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100538 CHECK_DATE(this);
539 var t = LOCAL_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000540 sec = ToNumber(sec);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100541 ms = %_ArgumentsLength() < 2 ? LOCAL_MS(this) : ToNumber(ms);
542 var time = MakeTime(LOCAL_HOUR(this), LOCAL_MIN(this), sec, ms);
543 return SET_LOCAL_DATE_VALUE(this, MakeDate(LOCAL_DAYS(this), time));
Andrei Popescu31002712010-02-23 13:46:05 +0000544}
545
546
547// ECMA 262 - 15.9.5.31
548function DateSetUTCSeconds(sec, ms) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100549 CHECK_DATE(this);
550 var t = UTC_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000551 sec = ToNumber(sec);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100552 ms = %_ArgumentsLength() < 2 ? UTC_MS(this) : ToNumber(ms);
553 var time = MakeTime(UTC_HOUR(this), UTC_MIN(this), sec, ms);
554 return SET_UTC_DATE_VALUE(this, MakeDate(UTC_DAYS(this), time));
Andrei Popescu31002712010-02-23 13:46:05 +0000555}
556
557
558// ECMA 262 - 15.9.5.33
559function DateSetMinutes(min, sec, ms) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100560 CHECK_DATE(this);
561 var t = LOCAL_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000562 min = ToNumber(min);
563 var argc = %_ArgumentsLength();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100564 sec = argc < 2 ? LOCAL_SEC(this) : ToNumber(sec);
565 ms = argc < 3 ? LOCAL_MS(this) : ToNumber(ms);
566 var time = MakeTime(LOCAL_HOUR(this), min, sec, ms);
567 return SET_LOCAL_DATE_VALUE(this, MakeDate(LOCAL_DAYS(this), time));
Andrei Popescu31002712010-02-23 13:46:05 +0000568}
569
570
571// ECMA 262 - 15.9.5.34
572function DateSetUTCMinutes(min, sec, ms) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100573 CHECK_DATE(this);
574 var t = UTC_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000575 min = ToNumber(min);
576 var argc = %_ArgumentsLength();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100577 sec = argc < 2 ? UTC_SEC(this) : ToNumber(sec);
578 ms = argc < 3 ? UTC_MS(this) : ToNumber(ms);
579 var time = MakeTime(UTC_HOUR(this), min, sec, ms);
580 return SET_UTC_DATE_VALUE(this, MakeDate(UTC_DAYS(this), time));
Andrei Popescu31002712010-02-23 13:46:05 +0000581}
582
583
584// ECMA 262 - 15.9.5.35
585function DateSetHours(hour, min, sec, ms) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100586 CHECK_DATE(this);
587 var t = LOCAL_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000588 hour = ToNumber(hour);
589 var argc = %_ArgumentsLength();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100590 min = argc < 2 ? LOCAL_MIN(this) : ToNumber(min);
591 sec = argc < 3 ? LOCAL_SEC(this) : ToNumber(sec);
592 ms = argc < 4 ? LOCAL_MS(this) : ToNumber(ms);
Andrei Popescu31002712010-02-23 13:46:05 +0000593 var time = MakeTime(hour, min, sec, ms);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100594 return SET_LOCAL_DATE_VALUE(this, MakeDate(LOCAL_DAYS(this), time));
Andrei Popescu31002712010-02-23 13:46:05 +0000595}
596
597
598// ECMA 262 - 15.9.5.34
599function DateSetUTCHours(hour, min, sec, ms) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100600 CHECK_DATE(this);
601 var t = UTC_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000602 hour = ToNumber(hour);
603 var argc = %_ArgumentsLength();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100604 min = argc < 2 ? UTC_MIN(this) : ToNumber(min);
605 sec = argc < 3 ? UTC_SEC(this) : ToNumber(sec);
606 ms = argc < 4 ? UTC_MS(this) : ToNumber(ms);
Andrei Popescu31002712010-02-23 13:46:05 +0000607 var time = MakeTime(hour, min, sec, ms);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100608 return SET_UTC_DATE_VALUE(this, MakeDate(UTC_DAYS(this), time));
Andrei Popescu31002712010-02-23 13:46:05 +0000609}
610
611
612// ECMA 262 - 15.9.5.36
613function DateSetDate(date) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100614 CHECK_DATE(this);
615 var t = LOCAL_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000616 date = ToNumber(date);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100617 var day = MakeDay(LOCAL_YEAR(this), LOCAL_MONTH(this), date);
618 return SET_LOCAL_DATE_VALUE(this, MakeDate(day, LOCAL_TIME_IN_DAY(this)));
Andrei Popescu31002712010-02-23 13:46:05 +0000619}
620
621
622// ECMA 262 - 15.9.5.37
623function DateSetUTCDate(date) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100624 CHECK_DATE(this);
625 var t = UTC_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000626 date = ToNumber(date);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100627 var day = MakeDay(UTC_YEAR(this), UTC_MONTH(this), date);
628 return SET_UTC_DATE_VALUE(this, MakeDate(day, UTC_TIME_IN_DAY(this)));
Andrei Popescu31002712010-02-23 13:46:05 +0000629}
630
631
632// ECMA 262 - 15.9.5.38
633function DateSetMonth(month, date) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100634 CHECK_DATE(this);
635 var t = LOCAL_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000636 month = ToNumber(month);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100637 date = %_ArgumentsLength() < 2 ? LOCAL_DAY(this) : ToNumber(date);
638 var day = MakeDay(LOCAL_YEAR(this), month, date);
639 return SET_LOCAL_DATE_VALUE(this, MakeDate(day, LOCAL_TIME_IN_DAY(this)));
Andrei Popescu31002712010-02-23 13:46:05 +0000640}
641
642
643// ECMA 262 - 15.9.5.39
644function DateSetUTCMonth(month, date) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100645 CHECK_DATE(this);
646 var t = UTC_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000647 month = ToNumber(month);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100648 date = %_ArgumentsLength() < 2 ? UTC_DAY(this) : ToNumber(date);
649 var day = MakeDay(UTC_YEAR(this), month, date);
650 return SET_UTC_DATE_VALUE(this, MakeDate(day, UTC_TIME_IN_DAY(this)));
Andrei Popescu31002712010-02-23 13:46:05 +0000651}
652
653
654// ECMA 262 - 15.9.5.40
655function DateSetFullYear(year, month, date) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100656 CHECK_DATE(this);
657 var t = LOCAL_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000658 year = ToNumber(year);
659 var argc = %_ArgumentsLength();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100660 var time ;
661 if (NUMBER_IS_NAN(t)) {
662 month = argc < 2 ? 0 : ToNumber(month);
663 date = argc < 3 ? 1 : ToNumber(date);
664 time = 0;
665 } else {
666 month = argc < 2 ? LOCAL_MONTH(this) : ToNumber(month);
667 date = argc < 3 ? LOCAL_DAY(this) : ToNumber(date);
668 time = LOCAL_TIME_IN_DAY(this);
669 }
Andrei Popescu31002712010-02-23 13:46:05 +0000670 var day = MakeDay(year, month, date);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100671 return SET_LOCAL_DATE_VALUE(this, MakeDate(day, time));
Andrei Popescu31002712010-02-23 13:46:05 +0000672}
673
674
675// ECMA 262 - 15.9.5.41
676function DateSetUTCFullYear(year, month, date) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100677 CHECK_DATE(this);
678 var t = UTC_DATE_VALUE(this);
Ben Murdoch85b71792012-04-11 18:30:58 +0100679 year = ToNumber(year);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100680 var argc = %_ArgumentsLength();
681 var time ;
682 if (NUMBER_IS_NAN(t)) {
683 month = argc < 2 ? 0 : ToNumber(month);
684 date = argc < 3 ? 1 : ToNumber(date);
685 time = 0;
686 } else {
687 month = argc < 2 ? UTC_MONTH(this) : ToNumber(month);
688 date = argc < 3 ? UTC_DAY(this) : ToNumber(date);
689 time = UTC_TIME_IN_DAY(this);
690 }
Andrei Popescu31002712010-02-23 13:46:05 +0000691 var day = MakeDay(year, month, date);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100692 return SET_UTC_DATE_VALUE(this, MakeDate(day, time));
Andrei Popescu31002712010-02-23 13:46:05 +0000693}
694
695
696// ECMA 262 - 15.9.5.42
697function DateToUTCString() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100698 CHECK_DATE(this);
699 var t = UTC_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000700 if (NUMBER_IS_NAN(t)) return kInvalidDate;
701 // Return UTC string of the form: Sat, 31 Jan 1970 23:00:00 GMT
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100702 return WeekDays[UTC_WEEKDAY(this)] + ', '
703 + TwoDigitString(UTC_DAY(this)) + ' '
704 + Months[UTC_MONTH(this)] + ' '
705 + UTC_YEAR(this) + ' '
706 + TimeStringUTC(this) + ' GMT';
Andrei Popescu31002712010-02-23 13:46:05 +0000707}
708
709
710// ECMA 262 - B.2.4
711function DateGetYear() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100712 CHECK_DATE(this);
713 return LOCAL_YEAR(this) - 1900;
Andrei Popescu31002712010-02-23 13:46:05 +0000714}
715
716
717// ECMA 262 - B.2.5
718function DateSetYear(year) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100719 CHECK_DATE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000720 year = ToNumber(year);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100721 if (NUMBER_IS_NAN(year)) return SET_UTC_DATE_VALUE(this, $NaN);
Andrei Popescu31002712010-02-23 13:46:05 +0000722 year = (0 <= TO_INTEGER(year) && TO_INTEGER(year) <= 99)
723 ? 1900 + TO_INTEGER(year) : year;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100724 var t = LOCAL_DATE_VALUE(this);
725 var month, date, time;
726 if (NUMBER_IS_NAN(t)) {
727 month = 0;
728 date = 1;
729 time = 0;
730 } else {
731 month = LOCAL_MONTH(this);
732 date = LOCAL_DAY(this);
733 time = LOCAL_TIME_IN_DAY(this);
734 }
735 var day = MakeDay(year, month, date);
736 return SET_LOCAL_DATE_VALUE(this, MakeDate(day, time));
Andrei Popescu31002712010-02-23 13:46:05 +0000737}
738
739
740// ECMA 262 - B.2.6
741//
742// Notice that this does not follow ECMA 262 completely. ECMA 262
743// says that toGMTString should be the same Function object as
744// toUTCString. JSC does not do this, so for compatibility we do not
745// do that either. Instead, we create a new function whose name
746// property will return toGMTString.
747function DateToGMTString() {
Steve Block1e0659c2011-05-24 12:43:12 +0100748 return %_CallFunction(this, DateToUTCString);
Andrei Popescu31002712010-02-23 13:46:05 +0000749}
750
751
752function PadInt(n, digits) {
753 if (digits == 1) return n;
754 return n < MathPow(10, digits - 1) ? '0' + PadInt(n, digits - 1) : n;
755}
756
757
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100758// ECMA 262 - 15.9.5.43
Andrei Popescu31002712010-02-23 13:46:05 +0000759function DateToISOString() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100760 CHECK_DATE(this);
761 var t = UTC_DATE_VALUE(this);
762 if (NUMBER_IS_NAN(t)) throw MakeRangeError("invalid_time_value", []);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000763 var year = this.getUTCFullYear();
764 var year_string;
765 if (year >= 0 && year <= 9999) {
766 year_string = PadInt(year, 4);
767 } else {
768 if (year < 0) {
769 year_string = "-" + PadInt(-year, 6);
770 } else {
771 year_string = "+" + PadInt(year, 6);
772 }
773 }
774 return year_string +
Ben Murdochb0fe1622011-05-05 13:52:32 +0100775 '-' + PadInt(this.getUTCMonth() + 1, 2) +
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000776 '-' + PadInt(this.getUTCDate(), 2) +
Ben Murdochb0fe1622011-05-05 13:52:32 +0100777 'T' + PadInt(this.getUTCHours(), 2) +
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000778 ':' + PadInt(this.getUTCMinutes(), 2) +
Ben Murdochb0fe1622011-05-05 13:52:32 +0100779 ':' + PadInt(this.getUTCSeconds(), 2) +
Andrei Popescu31002712010-02-23 13:46:05 +0000780 '.' + PadInt(this.getUTCMilliseconds(), 3) +
781 'Z';
782}
783
784
785function DateToJSON(key) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100786 var o = ToObject(this);
787 var tv = DefaultNumber(o);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000788 if (IS_NUMBER(tv) && !NUMBER_IS_FINITE(tv)) {
789 return null;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100790 }
791 return o.toISOString();
792}
793
794
795function ResetDateCache() {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100796 // Reset the timezone cache:
797 timezone_cache_time = $NaN;
798 timezone_cache_timezone = undefined;
799
Ben Murdochb0fe1622011-05-05 13:52:32 +0100800 // Reset the date cache:
801 cache = Date_cache;
802 cache.time = $NaN;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100803 cache.string = null;
Andrei Popescu31002712010-02-23 13:46:05 +0000804}
805
806
807// -------------------------------------------------------------------
808
Ben Murdoch589d6972011-11-30 16:04:58 +0000809function SetUpDate() {
810 %CheckIsBootstrapping();
811 // Set up non-enumerable properties of the Date object itself.
Andrei Popescu31002712010-02-23 13:46:05 +0000812 InstallFunctions($Date, DONT_ENUM, $Array(
813 "UTC", DateUTC,
814 "parse", DateParse,
815 "now", DateNow
816 ));
817
Ben Murdoch589d6972011-11-30 16:04:58 +0000818 // Set up non-enumerable constructor property of the Date prototype object.
Andrei Popescu31002712010-02-23 13:46:05 +0000819 %SetProperty($Date.prototype, "constructor", $Date, DONT_ENUM);
820
Ben Murdoch589d6972011-11-30 16:04:58 +0000821 // Set up non-enumerable functions of the Date prototype object and
Andrei Popescu31002712010-02-23 13:46:05 +0000822 // set their names.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100823 InstallFunctions($Date.prototype, DONT_ENUM, $Array(
Andrei Popescu31002712010-02-23 13:46:05 +0000824 "toString", DateToString,
825 "toDateString", DateToDateString,
826 "toTimeString", DateToTimeString,
827 "toLocaleString", DateToLocaleString,
828 "toLocaleDateString", DateToLocaleDateString,
829 "toLocaleTimeString", DateToLocaleTimeString,
830 "valueOf", DateValueOf,
831 "getTime", DateGetTime,
832 "getFullYear", DateGetFullYear,
833 "getUTCFullYear", DateGetUTCFullYear,
834 "getMonth", DateGetMonth,
835 "getUTCMonth", DateGetUTCMonth,
836 "getDate", DateGetDate,
837 "getUTCDate", DateGetUTCDate,
838 "getDay", DateGetDay,
839 "getUTCDay", DateGetUTCDay,
840 "getHours", DateGetHours,
841 "getUTCHours", DateGetUTCHours,
842 "getMinutes", DateGetMinutes,
843 "getUTCMinutes", DateGetUTCMinutes,
844 "getSeconds", DateGetSeconds,
845 "getUTCSeconds", DateGetUTCSeconds,
846 "getMilliseconds", DateGetMilliseconds,
847 "getUTCMilliseconds", DateGetUTCMilliseconds,
848 "getTimezoneOffset", DateGetTimezoneOffset,
849 "setTime", DateSetTime,
850 "setMilliseconds", DateSetMilliseconds,
851 "setUTCMilliseconds", DateSetUTCMilliseconds,
852 "setSeconds", DateSetSeconds,
853 "setUTCSeconds", DateSetUTCSeconds,
854 "setMinutes", DateSetMinutes,
855 "setUTCMinutes", DateSetUTCMinutes,
856 "setHours", DateSetHours,
857 "setUTCHours", DateSetUTCHours,
858 "setDate", DateSetDate,
859 "setUTCDate", DateSetUTCDate,
860 "setMonth", DateSetMonth,
861 "setUTCMonth", DateSetUTCMonth,
862 "setFullYear", DateSetFullYear,
863 "setUTCFullYear", DateSetUTCFullYear,
864 "toGMTString", DateToGMTString,
865 "toUTCString", DateToUTCString,
866 "getYear", DateGetYear,
867 "setYear", DateSetYear,
868 "toISOString", DateToISOString,
869 "toJSON", DateToJSON
870 ));
871}
872
Ben Murdoch589d6972011-11-30 16:04:58 +0000873SetUpDate();