blob: 75edf6d32d17c364023c39cb319c937c1421286d [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);
519 SET_LOCAL_DATE_VALUE(this, MakeDate(LOCAL_DAYS(this), time));
520 return this;
Andrei Popescu31002712010-02-23 13:46:05 +0000521}
522
523
524// ECMA 262 - 15.9.5.29
525function DateSetUTCMilliseconds(ms) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100526 CHECK_DATE(this);
527 var t = UTC_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000528 ms = ToNumber(ms);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100529 var time = MakeTime(UTC_HOUR(this),
530 UTC_MIN(this),
531 UTC_SEC(this),
532 ms);
533 return SET_UTC_DATE_VALUE(this, MakeDate(UTC_DAYS(this), time));
Andrei Popescu31002712010-02-23 13:46:05 +0000534}
535
536
537// ECMA 262 - 15.9.5.30
538function DateSetSeconds(sec, ms) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100539 CHECK_DATE(this);
540 var t = LOCAL_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000541 sec = ToNumber(sec);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100542 ms = %_ArgumentsLength() < 2 ? LOCAL_MS(this) : ToNumber(ms);
543 var time = MakeTime(LOCAL_HOUR(this), LOCAL_MIN(this), sec, ms);
544 return SET_LOCAL_DATE_VALUE(this, MakeDate(LOCAL_DAYS(this), time));
Andrei Popescu31002712010-02-23 13:46:05 +0000545}
546
547
548// ECMA 262 - 15.9.5.31
549function DateSetUTCSeconds(sec, ms) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100550 CHECK_DATE(this);
551 var t = UTC_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000552 sec = ToNumber(sec);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100553 ms = %_ArgumentsLength() < 2 ? UTC_MS(this) : ToNumber(ms);
554 var time = MakeTime(UTC_HOUR(this), UTC_MIN(this), sec, ms);
555 return SET_UTC_DATE_VALUE(this, MakeDate(UTC_DAYS(this), time));
Andrei Popescu31002712010-02-23 13:46:05 +0000556}
557
558
559// ECMA 262 - 15.9.5.33
560function DateSetMinutes(min, sec, ms) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100561 CHECK_DATE(this);
562 var t = LOCAL_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000563 min = ToNumber(min);
564 var argc = %_ArgumentsLength();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100565 sec = argc < 2 ? LOCAL_SEC(this) : ToNumber(sec);
566 ms = argc < 3 ? LOCAL_MS(this) : ToNumber(ms);
567 var time = MakeTime(LOCAL_HOUR(this), min, sec, ms);
568 return SET_LOCAL_DATE_VALUE(this, MakeDate(LOCAL_DAYS(this), time));
Andrei Popescu31002712010-02-23 13:46:05 +0000569}
570
571
572// ECMA 262 - 15.9.5.34
573function DateSetUTCMinutes(min, sec, ms) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100574 CHECK_DATE(this);
575 var t = UTC_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000576 min = ToNumber(min);
577 var argc = %_ArgumentsLength();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100578 sec = argc < 2 ? UTC_SEC(this) : ToNumber(sec);
579 ms = argc < 3 ? UTC_MS(this) : ToNumber(ms);
580 var time = MakeTime(UTC_HOUR(this), min, sec, ms);
581 return SET_UTC_DATE_VALUE(this, MakeDate(UTC_DAYS(this), time));
Andrei Popescu31002712010-02-23 13:46:05 +0000582}
583
584
585// ECMA 262 - 15.9.5.35
586function DateSetHours(hour, min, sec, ms) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100587 CHECK_DATE(this);
588 var t = LOCAL_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000589 hour = ToNumber(hour);
590 var argc = %_ArgumentsLength();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100591 min = argc < 2 ? LOCAL_MIN(this) : ToNumber(min);
592 sec = argc < 3 ? LOCAL_SEC(this) : ToNumber(sec);
593 ms = argc < 4 ? LOCAL_MS(this) : ToNumber(ms);
Andrei Popescu31002712010-02-23 13:46:05 +0000594 var time = MakeTime(hour, min, sec, ms);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100595 return SET_LOCAL_DATE_VALUE(this, MakeDate(LOCAL_DAYS(this), time));
Andrei Popescu31002712010-02-23 13:46:05 +0000596}
597
598
599// ECMA 262 - 15.9.5.34
600function DateSetUTCHours(hour, min, sec, ms) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100601 CHECK_DATE(this);
602 var t = UTC_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000603 hour = ToNumber(hour);
604 var argc = %_ArgumentsLength();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100605 min = argc < 2 ? UTC_MIN(this) : ToNumber(min);
606 sec = argc < 3 ? UTC_SEC(this) : ToNumber(sec);
607 ms = argc < 4 ? UTC_MS(this) : ToNumber(ms);
Andrei Popescu31002712010-02-23 13:46:05 +0000608 var time = MakeTime(hour, min, sec, ms);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100609 return SET_UTC_DATE_VALUE(this, MakeDate(UTC_DAYS(this), time));
Andrei Popescu31002712010-02-23 13:46:05 +0000610}
611
612
613// ECMA 262 - 15.9.5.36
614function DateSetDate(date) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100615 CHECK_DATE(this);
616 var t = LOCAL_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000617 date = ToNumber(date);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100618 var day = MakeDay(LOCAL_YEAR(this), LOCAL_MONTH(this), date);
619 return SET_LOCAL_DATE_VALUE(this, MakeDate(day, LOCAL_TIME_IN_DAY(this)));
Andrei Popescu31002712010-02-23 13:46:05 +0000620}
621
622
623// ECMA 262 - 15.9.5.37
624function DateSetUTCDate(date) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100625 CHECK_DATE(this);
626 var t = UTC_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000627 date = ToNumber(date);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100628 var day = MakeDay(UTC_YEAR(this), UTC_MONTH(this), date);
629 return SET_UTC_DATE_VALUE(this, MakeDate(day, UTC_TIME_IN_DAY(this)));
Andrei Popescu31002712010-02-23 13:46:05 +0000630}
631
632
633// ECMA 262 - 15.9.5.38
634function DateSetMonth(month, date) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100635 CHECK_DATE(this);
636 var t = LOCAL_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000637 month = ToNumber(month);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100638 date = %_ArgumentsLength() < 2 ? LOCAL_DAY(this) : ToNumber(date);
639 var day = MakeDay(LOCAL_YEAR(this), month, date);
640 return SET_LOCAL_DATE_VALUE(this, MakeDate(day, LOCAL_TIME_IN_DAY(this)));
Andrei Popescu31002712010-02-23 13:46:05 +0000641}
642
643
644// ECMA 262 - 15.9.5.39
645function DateSetUTCMonth(month, date) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100646 CHECK_DATE(this);
647 var t = UTC_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000648 month = ToNumber(month);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100649 date = %_ArgumentsLength() < 2 ? UTC_DAY(this) : ToNumber(date);
650 var day = MakeDay(UTC_YEAR(this), month, date);
651 return SET_UTC_DATE_VALUE(this, MakeDate(day, UTC_TIME_IN_DAY(this)));
Andrei Popescu31002712010-02-23 13:46:05 +0000652}
653
654
655// ECMA 262 - 15.9.5.40
656function DateSetFullYear(year, month, date) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100657 CHECK_DATE(this);
658 var t = LOCAL_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000659 year = ToNumber(year);
660 var argc = %_ArgumentsLength();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100661 var time ;
662 if (NUMBER_IS_NAN(t)) {
663 month = argc < 2 ? 0 : ToNumber(month);
664 date = argc < 3 ? 1 : ToNumber(date);
665 time = 0;
666 } else {
667 month = argc < 2 ? LOCAL_MONTH(this) : ToNumber(month);
668 date = argc < 3 ? LOCAL_DAY(this) : ToNumber(date);
669 time = LOCAL_TIME_IN_DAY(this);
670 }
Andrei Popescu31002712010-02-23 13:46:05 +0000671 var day = MakeDay(year, month, date);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100672 return SET_LOCAL_DATE_VALUE(this, MakeDate(day, time));
Andrei Popescu31002712010-02-23 13:46:05 +0000673}
674
675
676// ECMA 262 - 15.9.5.41
677function DateSetUTCFullYear(year, month, date) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100678 CHECK_DATE(this);
679 var t = UTC_DATE_VALUE(this);
Ben Murdoch85b71792012-04-11 18:30:58 +0100680 year = ToNumber(year);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100681 var argc = %_ArgumentsLength();
682 var time ;
683 if (NUMBER_IS_NAN(t)) {
684 month = argc < 2 ? 0 : ToNumber(month);
685 date = argc < 3 ? 1 : ToNumber(date);
686 time = 0;
687 } else {
688 month = argc < 2 ? UTC_MONTH(this) : ToNumber(month);
689 date = argc < 3 ? UTC_DAY(this) : ToNumber(date);
690 time = UTC_TIME_IN_DAY(this);
691 }
Andrei Popescu31002712010-02-23 13:46:05 +0000692 var day = MakeDay(year, month, date);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100693 return SET_UTC_DATE_VALUE(this, MakeDate(day, time));
Andrei Popescu31002712010-02-23 13:46:05 +0000694}
695
696
697// ECMA 262 - 15.9.5.42
698function DateToUTCString() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100699 CHECK_DATE(this);
700 var t = UTC_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000701 if (NUMBER_IS_NAN(t)) return kInvalidDate;
702 // Return UTC string of the form: Sat, 31 Jan 1970 23:00:00 GMT
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100703 return WeekDays[UTC_WEEKDAY(this)] + ', '
704 + TwoDigitString(UTC_DAY(this)) + ' '
705 + Months[UTC_MONTH(this)] + ' '
706 + UTC_YEAR(this) + ' '
707 + TimeStringUTC(this) + ' GMT';
Andrei Popescu31002712010-02-23 13:46:05 +0000708}
709
710
711// ECMA 262 - B.2.4
712function DateGetYear() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100713 CHECK_DATE(this);
714 return LOCAL_YEAR(this) - 1900;
Andrei Popescu31002712010-02-23 13:46:05 +0000715}
716
717
718// ECMA 262 - B.2.5
719function DateSetYear(year) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100720 CHECK_DATE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000721 year = ToNumber(year);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100722 if (NUMBER_IS_NAN(year)) return SET_UTC_DATE_VALUE(this, $NaN);
Andrei Popescu31002712010-02-23 13:46:05 +0000723 year = (0 <= TO_INTEGER(year) && TO_INTEGER(year) <= 99)
724 ? 1900 + TO_INTEGER(year) : year;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100725 var t = LOCAL_DATE_VALUE(this);
726 var month, date, time;
727 if (NUMBER_IS_NAN(t)) {
728 month = 0;
729 date = 1;
730 time = 0;
731 } else {
732 month = LOCAL_MONTH(this);
733 date = LOCAL_DAY(this);
734 time = LOCAL_TIME_IN_DAY(this);
735 }
736 var day = MakeDay(year, month, date);
737 return SET_LOCAL_DATE_VALUE(this, MakeDate(day, time));
Andrei Popescu31002712010-02-23 13:46:05 +0000738}
739
740
741// ECMA 262 - B.2.6
742//
743// Notice that this does not follow ECMA 262 completely. ECMA 262
744// says that toGMTString should be the same Function object as
745// toUTCString. JSC does not do this, so for compatibility we do not
746// do that either. Instead, we create a new function whose name
747// property will return toGMTString.
748function DateToGMTString() {
Steve Block1e0659c2011-05-24 12:43:12 +0100749 return %_CallFunction(this, DateToUTCString);
Andrei Popescu31002712010-02-23 13:46:05 +0000750}
751
752
753function PadInt(n, digits) {
754 if (digits == 1) return n;
755 return n < MathPow(10, digits - 1) ? '0' + PadInt(n, digits - 1) : n;
756}
757
758
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100759// ECMA 262 - 15.9.5.43
Andrei Popescu31002712010-02-23 13:46:05 +0000760function DateToISOString() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100761 CHECK_DATE(this);
762 var t = UTC_DATE_VALUE(this);
763 if (NUMBER_IS_NAN(t)) throw MakeRangeError("invalid_time_value", []);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000764 var year = this.getUTCFullYear();
765 var year_string;
766 if (year >= 0 && year <= 9999) {
767 year_string = PadInt(year, 4);
768 } else {
769 if (year < 0) {
770 year_string = "-" + PadInt(-year, 6);
771 } else {
772 year_string = "+" + PadInt(year, 6);
773 }
774 }
775 return year_string +
Ben Murdochb0fe1622011-05-05 13:52:32 +0100776 '-' + PadInt(this.getUTCMonth() + 1, 2) +
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000777 '-' + PadInt(this.getUTCDate(), 2) +
Ben Murdochb0fe1622011-05-05 13:52:32 +0100778 'T' + PadInt(this.getUTCHours(), 2) +
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000779 ':' + PadInt(this.getUTCMinutes(), 2) +
Ben Murdochb0fe1622011-05-05 13:52:32 +0100780 ':' + PadInt(this.getUTCSeconds(), 2) +
Andrei Popescu31002712010-02-23 13:46:05 +0000781 '.' + PadInt(this.getUTCMilliseconds(), 3) +
782 'Z';
783}
784
785
786function DateToJSON(key) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100787 var o = ToObject(this);
788 var tv = DefaultNumber(o);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000789 if (IS_NUMBER(tv) && !NUMBER_IS_FINITE(tv)) {
790 return null;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100791 }
792 return o.toISOString();
793}
794
795
796function ResetDateCache() {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100797 // Reset the timezone cache:
798 timezone_cache_time = $NaN;
799 timezone_cache_timezone = undefined;
800
Ben Murdochb0fe1622011-05-05 13:52:32 +0100801 // Reset the date cache:
802 cache = Date_cache;
803 cache.time = $NaN;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100804 cache.string = null;
Andrei Popescu31002712010-02-23 13:46:05 +0000805}
806
807
808// -------------------------------------------------------------------
809
Ben Murdoch589d6972011-11-30 16:04:58 +0000810function SetUpDate() {
811 %CheckIsBootstrapping();
812 // Set up non-enumerable properties of the Date object itself.
Andrei Popescu31002712010-02-23 13:46:05 +0000813 InstallFunctions($Date, DONT_ENUM, $Array(
814 "UTC", DateUTC,
815 "parse", DateParse,
816 "now", DateNow
817 ));
818
Ben Murdoch589d6972011-11-30 16:04:58 +0000819 // Set up non-enumerable constructor property of the Date prototype object.
Andrei Popescu31002712010-02-23 13:46:05 +0000820 %SetProperty($Date.prototype, "constructor", $Date, DONT_ENUM);
821
Ben Murdoch589d6972011-11-30 16:04:58 +0000822 // Set up non-enumerable functions of the Date prototype object and
Andrei Popescu31002712010-02-23 13:46:05 +0000823 // set their names.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100824 InstallFunctions($Date.prototype, DONT_ENUM, $Array(
Andrei Popescu31002712010-02-23 13:46:05 +0000825 "toString", DateToString,
826 "toDateString", DateToDateString,
827 "toTimeString", DateToTimeString,
828 "toLocaleString", DateToLocaleString,
829 "toLocaleDateString", DateToLocaleDateString,
830 "toLocaleTimeString", DateToLocaleTimeString,
831 "valueOf", DateValueOf,
832 "getTime", DateGetTime,
833 "getFullYear", DateGetFullYear,
834 "getUTCFullYear", DateGetUTCFullYear,
835 "getMonth", DateGetMonth,
836 "getUTCMonth", DateGetUTCMonth,
837 "getDate", DateGetDate,
838 "getUTCDate", DateGetUTCDate,
839 "getDay", DateGetDay,
840 "getUTCDay", DateGetUTCDay,
841 "getHours", DateGetHours,
842 "getUTCHours", DateGetUTCHours,
843 "getMinutes", DateGetMinutes,
844 "getUTCMinutes", DateGetUTCMinutes,
845 "getSeconds", DateGetSeconds,
846 "getUTCSeconds", DateGetUTCSeconds,
847 "getMilliseconds", DateGetMilliseconds,
848 "getUTCMilliseconds", DateGetUTCMilliseconds,
849 "getTimezoneOffset", DateGetTimezoneOffset,
850 "setTime", DateSetTime,
851 "setMilliseconds", DateSetMilliseconds,
852 "setUTCMilliseconds", DateSetUTCMilliseconds,
853 "setSeconds", DateSetSeconds,
854 "setUTCSeconds", DateSetUTCSeconds,
855 "setMinutes", DateSetMinutes,
856 "setUTCMinutes", DateSetUTCMinutes,
857 "setHours", DateSetHours,
858 "setUTCHours", DateSetUTCHours,
859 "setDate", DateSetDate,
860 "setUTCDate", DateSetUTCDate,
861 "setMonth", DateSetMonth,
862 "setUTCMonth", DateSetUTCMonth,
863 "setFullYear", DateSetFullYear,
864 "setUTCFullYear", DateSetUTCFullYear,
865 "toGMTString", DateToGMTString,
866 "toUTCString", DateToUTCString,
867 "getYear", DateGetYear,
868 "setYear", DateSetYear,
869 "toISOString", DateToISOString,
870 "toJSON", DateToJSON
871 ));
872}
873
Ben Murdoch589d6972011-11-30 16:04:58 +0000874SetUpDate();