blob: 87c87bfda6023355e47a1908dd081701640e124e [file] [log] [blame]
Andrei Popescu31002712010-02-23 13:46:05 +00001// Copyright 2006-2008 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Andrei Popescu31002712010-02-23 13:46:05 +00004
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005"use strict";
Andrei Popescu31002712010-02-23 13:46:05 +00006
7// This file relies on the fact that the following declarations have been made
8// in v8natives.js:
Ben Murdoch3ef787d2012-04-12 10:51:47 +01009// var $isFinite = GlobalIsFinite;
Andrei Popescu31002712010-02-23 13:46:05 +000010
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011var $Date = global.Date;
12
Andrei Popescu31002712010-02-23 13:46:05 +000013// -------------------------------------------------------------------
14
15// This file contains date support implemented in JavaScript.
16
Andrei Popescu31002712010-02-23 13:46:05 +000017// Helper function to throw error.
18function ThrowDateTypeError() {
19 throw new $TypeError('this is not a Date object.');
20}
21
Andrei Popescu31002712010-02-23 13:46:05 +000022
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023var timezone_cache_time = NAN;
Andrei Popescu31002712010-02-23 13:46:05 +000024var timezone_cache_timezone;
25
26function LocalTimezone(t) {
27 if (NUMBER_IS_NAN(t)) return "";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000028 CheckDateCacheCurrent();
Andrei Popescu31002712010-02-23 13:46:05 +000029 if (t == timezone_cache_time) {
30 return timezone_cache_timezone;
31 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010032 var timezone = %DateLocalTimezone(t);
Andrei Popescu31002712010-02-23 13:46:05 +000033 timezone_cache_time = t;
34 timezone_cache_timezone = timezone;
35 return timezone;
36}
37
38
Andrei Popescu31002712010-02-23 13:46:05 +000039function UTC(time) {
40 if (NUMBER_IS_NAN(time)) return time;
Andrei Popescu6599b9d2010-04-28 13:01:47 +010041 // local_time_offset is needed before the call to DaylightSavingsOffset,
42 // so it may be uninitialized.
Ben Murdoch3ef787d2012-04-12 10:51:47 +010043 return %DateToUTC(time);
Andrei Popescu31002712010-02-23 13:46:05 +000044}
45
46
47// ECMA 262 - 15.9.1.11
48function MakeTime(hour, min, sec, ms) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000049 if (!$isFinite(hour)) return NAN;
50 if (!$isFinite(min)) return NAN;
51 if (!$isFinite(sec)) return NAN;
52 if (!$isFinite(ms)) return NAN;
Andrei Popescu31002712010-02-23 13:46:05 +000053 return TO_INTEGER(hour) * msPerHour
54 + TO_INTEGER(min) * msPerMinute
55 + TO_INTEGER(sec) * msPerSecond
56 + TO_INTEGER(ms);
57}
58
59
60// ECMA 262 - 15.9.1.12
61function TimeInYear(year) {
62 return DaysInYear(year) * msPerDay;
63}
64
65
Andrei Popescu31002712010-02-23 13:46:05 +000066// Compute number of days given a year, month, date.
67// Note that month and date can lie outside the normal range.
68// For example:
69// MakeDay(2007, -4, 20) --> MakeDay(2006, 8, 20)
70// MakeDay(2007, -33, 1) --> MakeDay(2004, 3, 1)
71// MakeDay(2007, 14, -50) --> MakeDay(2007, 8, 11)
72function MakeDay(year, month, date) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000073 if (!$isFinite(year) || !$isFinite(month) || !$isFinite(date)) return NAN;
Andrei Popescu31002712010-02-23 13:46:05 +000074
Steve Block8defd9f2010-07-08 12:39:36 +010075 // Convert to integer and map -0 to 0.
76 year = TO_INTEGER_MAP_MINUS_ZERO(year);
77 month = TO_INTEGER_MAP_MINUS_ZERO(month);
78 date = TO_INTEGER_MAP_MINUS_ZERO(date);
Andrei Popescu31002712010-02-23 13:46:05 +000079
Steve Block6ded16b2010-05-10 14:33:55 +010080 if (year < kMinYear || year > kMaxYear ||
Ben Murdoch3ef787d2012-04-12 10:51:47 +010081 month < kMinMonth || month > kMaxMonth) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000082 return NAN;
Andrei Popescu31002712010-02-23 13:46:05 +000083 }
84
Ben Murdoch3ef787d2012-04-12 10:51:47 +010085 // Now we rely on year and month being SMIs.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000086 return %DateMakeDay(year | 0, month | 0) + date - 1;
Andrei Popescu31002712010-02-23 13:46:05 +000087}
88
89
90// ECMA 262 - 15.9.1.13
91function MakeDate(day, time) {
Ben Murdochb0fe1622011-05-05 13:52:32 +010092 var time = day * msPerDay + time;
93 // Some of our runtime funtions for computing UTC(time) rely on
94 // times not being significantly larger than MAX_TIME_MS. If there
95 // is no way that the time can be within range even after UTC
96 // conversion we return NaN immediately instead of relying on
97 // TimeClip to do it.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000098 if ($abs(time) > MAX_TIME_BEFORE_UTC) return NAN;
Ben Murdochb0fe1622011-05-05 13:52:32 +010099 return time;
Andrei Popescu31002712010-02-23 13:46:05 +0000100}
101
102
103// ECMA 262 - 15.9.1.14
104function TimeClip(time) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000105 if (!$isFinite(time)) return NAN;
106 if ($abs(time) > MAX_TIME_MS) return NAN;
Andrei Popescu31002712010-02-23 13:46:05 +0000107 return TO_INTEGER(time);
108}
109
110
111// The Date cache is used to limit the cost of parsing the same Date
112// strings over and over again.
113var Date_cache = {
114 // Cached time value.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000115 time: 0,
Andrei Popescu31002712010-02-23 13:46:05 +0000116 // String input for which the cached time is valid.
117 string: null
118};
119
120
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000121function DateConstructor(year, month, date, hours, minutes, seconds, ms) {
Andrei Popescu31002712010-02-23 13:46:05 +0000122 if (!%_IsConstructCall()) {
123 // ECMA 262 - 15.9.2
124 return (new $Date()).toString();
125 }
126
127 // ECMA 262 - 15.9.3
128 var argc = %_ArgumentsLength();
129 var value;
130 if (argc == 0) {
131 value = %DateCurrentTime();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100132 SET_UTC_DATE_VALUE(this, value);
Andrei Popescu31002712010-02-23 13:46:05 +0000133 } else if (argc == 1) {
134 if (IS_NUMBER(year)) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100135 value = year;
Andrei Popescu31002712010-02-23 13:46:05 +0000136 } else if (IS_STRING(year)) {
137 // Probe the Date cache. If we already have a time value for the
138 // given time, we re-use that instead of parsing the string again.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000139 CheckDateCacheCurrent();
Andrei Popescu31002712010-02-23 13:46:05 +0000140 var cache = Date_cache;
141 if (cache.string === year) {
142 value = cache.time;
143 } else {
144 value = DateParse(year);
145 if (!NUMBER_IS_NAN(value)) {
146 cache.time = value;
Andrei Popescu31002712010-02-23 13:46:05 +0000147 cache.string = year;
148 }
149 }
150
151 } else {
152 // According to ECMA 262, no hint should be given for this
153 // conversion. However, ToPrimitive defaults to STRING_HINT for
154 // Date objects which will lose precision when the Date
155 // constructor is called with another Date object as its
156 // argument. We therefore use NUMBER_HINT for the conversion,
157 // which is the default for everything else than Date objects.
158 // This makes us behave like KJS and SpiderMonkey.
159 var time = ToPrimitive(year, NUMBER_HINT);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100160 value = IS_STRING(time) ? DateParse(time) : ToNumber(time);
Andrei Popescu31002712010-02-23 13:46:05 +0000161 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100162 SET_UTC_DATE_VALUE(this, value);
Andrei Popescu31002712010-02-23 13:46:05 +0000163 } else {
164 year = ToNumber(year);
165 month = ToNumber(month);
166 date = argc > 2 ? ToNumber(date) : 1;
167 hours = argc > 3 ? ToNumber(hours) : 0;
168 minutes = argc > 4 ? ToNumber(minutes) : 0;
169 seconds = argc > 5 ? ToNumber(seconds) : 0;
170 ms = argc > 6 ? ToNumber(ms) : 0;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100171 year = (!NUMBER_IS_NAN(year) &&
172 0 <= TO_INTEGER(year) &&
173 TO_INTEGER(year) <= 99) ? 1900 + TO_INTEGER(year) : year;
Andrei Popescu31002712010-02-23 13:46:05 +0000174 var day = MakeDay(year, month, date);
175 var time = MakeTime(hours, minutes, seconds, ms);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100176 value = MakeDate(day, time);
177 SET_LOCAL_DATE_VALUE(this, value);
Andrei Popescu31002712010-02-23 13:46:05 +0000178 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000179}
Andrei Popescu31002712010-02-23 13:46:05 +0000180
181
182var WeekDays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100183var Months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
184 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
Andrei Popescu31002712010-02-23 13:46:05 +0000185
186
187function TwoDigitString(value) {
188 return value < 10 ? "0" + value : "" + value;
189}
190
191
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100192function DateString(date) {
193 return WeekDays[LOCAL_WEEKDAY(date)] + ' '
194 + Months[LOCAL_MONTH(date)] + ' '
195 + TwoDigitString(LOCAL_DAY(date)) + ' '
196 + LOCAL_YEAR(date);
Andrei Popescu31002712010-02-23 13:46:05 +0000197}
198
199
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100200var LongWeekDays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday',
201 'Thursday', 'Friday', 'Saturday'];
202var LongMonths = ['January', 'February', 'March', 'April', 'May', 'June',
203 'July', 'August', 'September', 'October', 'November', 'December'];
Andrei Popescu31002712010-02-23 13:46:05 +0000204
205
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100206function LongDateString(date) {
207 return LongWeekDays[LOCAL_WEEKDAY(date)] + ', '
208 + LongMonths[LOCAL_MONTH(date)] + ' '
209 + TwoDigitString(LOCAL_DAY(date)) + ', '
210 + LOCAL_YEAR(date);
Andrei Popescu31002712010-02-23 13:46:05 +0000211}
212
213
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100214function TimeString(date) {
215 return TwoDigitString(LOCAL_HOUR(date)) + ':'
216 + TwoDigitString(LOCAL_MIN(date)) + ':'
217 + TwoDigitString(LOCAL_SEC(date));
Andrei Popescu31002712010-02-23 13:46:05 +0000218}
219
220
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100221function TimeStringUTC(date) {
222 return TwoDigitString(UTC_HOUR(date)) + ':'
223 + TwoDigitString(UTC_MIN(date)) + ':'
224 + TwoDigitString(UTC_SEC(date));
225}
Ben Murdochd69d2e32010-03-30 12:55:27 +0100226
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100227
228function LocalTimezoneString(date) {
229 var timezone = LocalTimezone(UTC_DATE_VALUE(date));
230
231 var timezoneOffset = -TIMEZONE_OFFSET(date);
Andrei Popescu31002712010-02-23 13:46:05 +0000232 var sign = (timezoneOffset >= 0) ? 1 : -1;
233 var hours = FLOOR((sign * timezoneOffset)/60);
234 var min = FLOOR((sign * timezoneOffset)%60);
235 var gmt = ' GMT' + ((sign == 1) ? '+' : '-') +
236 TwoDigitString(hours) + TwoDigitString(min);
Ben Murdochd69d2e32010-03-30 12:55:27 +0100237 return gmt + ' (' + timezone + ')';
Andrei Popescu31002712010-02-23 13:46:05 +0000238}
239
240
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100241function DatePrintString(date) {
242 return DateString(date) + ' ' + TimeString(date);
Andrei Popescu31002712010-02-23 13:46:05 +0000243}
244
245// -------------------------------------------------------------------
246
247// Reused output buffer. Used when parsing date strings.
Steve Block6ded16b2010-05-10 14:33:55 +0100248var parse_buffer = $Array(8);
Andrei Popescu31002712010-02-23 13:46:05 +0000249
250// ECMA 262 - 15.9.4.2
251function DateParse(string) {
252 var arr = %DateParseString(ToString(string), parse_buffer);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000253 if (IS_NULL(arr)) return NAN;
Andrei Popescu31002712010-02-23 13:46:05 +0000254
255 var day = MakeDay(arr[0], arr[1], arr[2]);
Steve Block6ded16b2010-05-10 14:33:55 +0100256 var time = MakeTime(arr[3], arr[4], arr[5], arr[6]);
Andrei Popescu31002712010-02-23 13:46:05 +0000257 var date = MakeDate(day, time);
258
Steve Block6ded16b2010-05-10 14:33:55 +0100259 if (IS_NULL(arr[7])) {
Andrei Popescu31002712010-02-23 13:46:05 +0000260 return TimeClip(UTC(date));
261 } else {
Steve Block6ded16b2010-05-10 14:33:55 +0100262 return TimeClip(date - arr[7] * 1000);
Andrei Popescu31002712010-02-23 13:46:05 +0000263 }
264}
265
266
267// ECMA 262 - 15.9.4.3
268function DateUTC(year, month, date, hours, minutes, seconds, ms) {
269 year = ToNumber(year);
270 month = ToNumber(month);
271 var argc = %_ArgumentsLength();
272 date = argc > 2 ? ToNumber(date) : 1;
273 hours = argc > 3 ? ToNumber(hours) : 0;
274 minutes = argc > 4 ? ToNumber(minutes) : 0;
275 seconds = argc > 5 ? ToNumber(seconds) : 0;
276 ms = argc > 6 ? ToNumber(ms) : 0;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100277 year = (!NUMBER_IS_NAN(year) &&
278 0 <= TO_INTEGER(year) &&
279 TO_INTEGER(year) <= 99) ? 1900 + TO_INTEGER(year) : year;
Andrei Popescu31002712010-02-23 13:46:05 +0000280 var day = MakeDay(year, month, date);
281 var time = MakeTime(hours, minutes, seconds, ms);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100282 return TimeClip(MakeDate(day, time));
Andrei Popescu31002712010-02-23 13:46:05 +0000283}
284
285
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000286// ECMA 262 - 15.9.4.4
Andrei Popescu31002712010-02-23 13:46:05 +0000287function DateNow() {
288 return %DateCurrentTime();
289}
290
291
292// ECMA 262 - 15.9.5.2
293function DateToString() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100294 var t = UTC_DATE_VALUE(this)
Andrei Popescu31002712010-02-23 13:46:05 +0000295 if (NUMBER_IS_NAN(t)) return kInvalidDate;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100296 var time_zone_string = LocalTimezoneString(this)
297 return DatePrintString(this) + time_zone_string;
Andrei Popescu31002712010-02-23 13:46:05 +0000298}
299
300
301// ECMA 262 - 15.9.5.3
302function DateToDateString() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100303 var t = UTC_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000304 if (NUMBER_IS_NAN(t)) return kInvalidDate;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100305 return DateString(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000306}
307
308
309// ECMA 262 - 15.9.5.4
310function DateToTimeString() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100311 var t = UTC_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000312 if (NUMBER_IS_NAN(t)) return kInvalidDate;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100313 var time_zone_string = LocalTimezoneString(this);
314 return TimeString(this) + time_zone_string;
Andrei Popescu31002712010-02-23 13:46:05 +0000315}
316
317
318// ECMA 262 - 15.9.5.5
319function DateToLocaleString() {
Steve Block1e0659c2011-05-24 12:43:12 +0100320 return %_CallFunction(this, DateToString);
Andrei Popescu31002712010-02-23 13:46:05 +0000321}
322
323
324// ECMA 262 - 15.9.5.6
325function DateToLocaleDateString() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100326 var t = UTC_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000327 if (NUMBER_IS_NAN(t)) return kInvalidDate;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100328 return LongDateString(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000329}
330
331
332// ECMA 262 - 15.9.5.7
333function DateToLocaleTimeString() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100334 var t = UTC_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000335 if (NUMBER_IS_NAN(t)) return kInvalidDate;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100336 return TimeString(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000337}
338
339
340// ECMA 262 - 15.9.5.8
341function DateValueOf() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100342 return UTC_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000343}
344
345
346// ECMA 262 - 15.9.5.9
Andrei Popescu402d9372010-02-26 13:31:12 +0000347function DateGetTime() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100348 return UTC_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000349}
350
351
352// ECMA 262 - 15.9.5.10
353function DateGetFullYear() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100354 return LOCAL_YEAR(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000355}
356
357
358// ECMA 262 - 15.9.5.11
359function DateGetUTCFullYear() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100360 return UTC_YEAR(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000361}
362
363
364// ECMA 262 - 15.9.5.12
365function DateGetMonth() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100366 return LOCAL_MONTH(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000367}
368
369
370// ECMA 262 - 15.9.5.13
371function DateGetUTCMonth() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100372 return UTC_MONTH(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000373}
374
375
376// ECMA 262 - 15.9.5.14
377function DateGetDate() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100378 return LOCAL_DAY(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000379}
380
381
382// ECMA 262 - 15.9.5.15
383function DateGetUTCDate() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100384 return UTC_DAY(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000385}
386
387
388// ECMA 262 - 15.9.5.16
389function DateGetDay() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100390 return LOCAL_WEEKDAY(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000391}
392
393
394// ECMA 262 - 15.9.5.17
395function DateGetUTCDay() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100396 return UTC_WEEKDAY(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000397}
398
399
400// ECMA 262 - 15.9.5.18
401function DateGetHours() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100402 return LOCAL_HOUR(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000403}
404
405
406// ECMA 262 - 15.9.5.19
407function DateGetUTCHours() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100408 return UTC_HOUR(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000409}
410
411
412// ECMA 262 - 15.9.5.20
413function DateGetMinutes() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100414 return LOCAL_MIN(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000415}
416
417
418// ECMA 262 - 15.9.5.21
419function DateGetUTCMinutes() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100420 return UTC_MIN(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000421}
422
423
424// ECMA 262 - 15.9.5.22
425function DateGetSeconds() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100426 return LOCAL_SEC(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000427}
428
429
430// ECMA 262 - 15.9.5.23
431function DateGetUTCSeconds() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100432 return UTC_SEC(this)
Andrei Popescu31002712010-02-23 13:46:05 +0000433}
434
435
436// ECMA 262 - 15.9.5.24
437function DateGetMilliseconds() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100438 return LOCAL_MS(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000439}
440
441
442// ECMA 262 - 15.9.5.25
443function DateGetUTCMilliseconds() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100444 return UTC_MS(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000445}
446
447
448// ECMA 262 - 15.9.5.26
449function DateGetTimezoneOffset() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100450 return TIMEZONE_OFFSET(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000451}
452
453
454// ECMA 262 - 15.9.5.27
455function DateSetTime(ms) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100456 CHECK_DATE(this);
457 SET_UTC_DATE_VALUE(this, ToNumber(ms));
458 return UTC_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000459}
460
461
462// ECMA 262 - 15.9.5.28
463function DateSetMilliseconds(ms) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100464 var t = LOCAL_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000465 ms = ToNumber(ms);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100466 var time = MakeTime(LOCAL_HOUR(this), LOCAL_MIN(this), LOCAL_SEC(this), ms);
Ben Murdoch84774f42012-05-17 10:59:30 +0100467 return SET_LOCAL_DATE_VALUE(this, MakeDate(LOCAL_DAYS(this), time));
Andrei Popescu31002712010-02-23 13:46:05 +0000468}
469
470
471// ECMA 262 - 15.9.5.29
472function DateSetUTCMilliseconds(ms) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100473 var t = UTC_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000474 ms = ToNumber(ms);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100475 var time = MakeTime(UTC_HOUR(this),
476 UTC_MIN(this),
477 UTC_SEC(this),
478 ms);
479 return SET_UTC_DATE_VALUE(this, MakeDate(UTC_DAYS(this), time));
Andrei Popescu31002712010-02-23 13:46:05 +0000480}
481
482
483// ECMA 262 - 15.9.5.30
484function DateSetSeconds(sec, ms) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100485 var t = LOCAL_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000486 sec = ToNumber(sec);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100487 ms = %_ArgumentsLength() < 2 ? LOCAL_MS(this) : ToNumber(ms);
488 var time = MakeTime(LOCAL_HOUR(this), LOCAL_MIN(this), sec, ms);
489 return SET_LOCAL_DATE_VALUE(this, MakeDate(LOCAL_DAYS(this), time));
Andrei Popescu31002712010-02-23 13:46:05 +0000490}
491
492
493// ECMA 262 - 15.9.5.31
494function DateSetUTCSeconds(sec, ms) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100495 var t = UTC_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000496 sec = ToNumber(sec);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100497 ms = %_ArgumentsLength() < 2 ? UTC_MS(this) : ToNumber(ms);
498 var time = MakeTime(UTC_HOUR(this), UTC_MIN(this), sec, ms);
499 return SET_UTC_DATE_VALUE(this, MakeDate(UTC_DAYS(this), time));
Andrei Popescu31002712010-02-23 13:46:05 +0000500}
501
502
503// ECMA 262 - 15.9.5.33
504function DateSetMinutes(min, sec, ms) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100505 var t = LOCAL_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000506 min = ToNumber(min);
507 var argc = %_ArgumentsLength();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100508 sec = argc < 2 ? LOCAL_SEC(this) : ToNumber(sec);
509 ms = argc < 3 ? LOCAL_MS(this) : ToNumber(ms);
510 var time = MakeTime(LOCAL_HOUR(this), min, sec, ms);
511 return SET_LOCAL_DATE_VALUE(this, MakeDate(LOCAL_DAYS(this), time));
Andrei Popescu31002712010-02-23 13:46:05 +0000512}
513
514
515// ECMA 262 - 15.9.5.34
516function DateSetUTCMinutes(min, sec, ms) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100517 var t = UTC_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000518 min = ToNumber(min);
519 var argc = %_ArgumentsLength();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100520 sec = argc < 2 ? UTC_SEC(this) : ToNumber(sec);
521 ms = argc < 3 ? UTC_MS(this) : ToNumber(ms);
522 var time = MakeTime(UTC_HOUR(this), min, sec, ms);
523 return SET_UTC_DATE_VALUE(this, MakeDate(UTC_DAYS(this), time));
Andrei Popescu31002712010-02-23 13:46:05 +0000524}
525
526
527// ECMA 262 - 15.9.5.35
528function DateSetHours(hour, min, sec, ms) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100529 var t = LOCAL_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000530 hour = ToNumber(hour);
531 var argc = %_ArgumentsLength();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100532 min = argc < 2 ? LOCAL_MIN(this) : ToNumber(min);
533 sec = argc < 3 ? LOCAL_SEC(this) : ToNumber(sec);
534 ms = argc < 4 ? LOCAL_MS(this) : ToNumber(ms);
Andrei Popescu31002712010-02-23 13:46:05 +0000535 var time = MakeTime(hour, min, sec, ms);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100536 return SET_LOCAL_DATE_VALUE(this, MakeDate(LOCAL_DAYS(this), time));
Andrei Popescu31002712010-02-23 13:46:05 +0000537}
538
539
540// ECMA 262 - 15.9.5.34
541function DateSetUTCHours(hour, min, sec, ms) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100542 var t = UTC_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000543 hour = ToNumber(hour);
544 var argc = %_ArgumentsLength();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100545 min = argc < 2 ? UTC_MIN(this) : ToNumber(min);
546 sec = argc < 3 ? UTC_SEC(this) : ToNumber(sec);
547 ms = argc < 4 ? UTC_MS(this) : ToNumber(ms);
Andrei Popescu31002712010-02-23 13:46:05 +0000548 var time = MakeTime(hour, min, sec, ms);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100549 return SET_UTC_DATE_VALUE(this, MakeDate(UTC_DAYS(this), time));
Andrei Popescu31002712010-02-23 13:46:05 +0000550}
551
552
553// ECMA 262 - 15.9.5.36
554function DateSetDate(date) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100555 var t = LOCAL_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000556 date = ToNumber(date);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100557 var day = MakeDay(LOCAL_YEAR(this), LOCAL_MONTH(this), date);
558 return SET_LOCAL_DATE_VALUE(this, MakeDate(day, LOCAL_TIME_IN_DAY(this)));
Andrei Popescu31002712010-02-23 13:46:05 +0000559}
560
561
562// ECMA 262 - 15.9.5.37
563function DateSetUTCDate(date) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100564 var t = UTC_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000565 date = ToNumber(date);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100566 var day = MakeDay(UTC_YEAR(this), UTC_MONTH(this), date);
567 return SET_UTC_DATE_VALUE(this, MakeDate(day, UTC_TIME_IN_DAY(this)));
Andrei Popescu31002712010-02-23 13:46:05 +0000568}
569
570
571// ECMA 262 - 15.9.5.38
572function DateSetMonth(month, date) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100573 var t = LOCAL_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000574 month = ToNumber(month);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100575 date = %_ArgumentsLength() < 2 ? LOCAL_DAY(this) : ToNumber(date);
576 var day = MakeDay(LOCAL_YEAR(this), month, date);
577 return SET_LOCAL_DATE_VALUE(this, MakeDate(day, LOCAL_TIME_IN_DAY(this)));
Andrei Popescu31002712010-02-23 13:46:05 +0000578}
579
580
581// ECMA 262 - 15.9.5.39
582function DateSetUTCMonth(month, date) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100583 var t = UTC_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000584 month = ToNumber(month);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100585 date = %_ArgumentsLength() < 2 ? UTC_DAY(this) : ToNumber(date);
586 var day = MakeDay(UTC_YEAR(this), month, date);
587 return SET_UTC_DATE_VALUE(this, MakeDate(day, UTC_TIME_IN_DAY(this)));
Andrei Popescu31002712010-02-23 13:46:05 +0000588}
589
590
591// ECMA 262 - 15.9.5.40
592function DateSetFullYear(year, month, date) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100593 var t = LOCAL_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000594 year = ToNumber(year);
595 var argc = %_ArgumentsLength();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100596 var time ;
597 if (NUMBER_IS_NAN(t)) {
598 month = argc < 2 ? 0 : ToNumber(month);
599 date = argc < 3 ? 1 : ToNumber(date);
600 time = 0;
601 } else {
602 month = argc < 2 ? LOCAL_MONTH(this) : ToNumber(month);
603 date = argc < 3 ? LOCAL_DAY(this) : ToNumber(date);
604 time = LOCAL_TIME_IN_DAY(this);
605 }
Andrei Popescu31002712010-02-23 13:46:05 +0000606 var day = MakeDay(year, month, date);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100607 return SET_LOCAL_DATE_VALUE(this, MakeDate(day, time));
Andrei Popescu31002712010-02-23 13:46:05 +0000608}
609
610
611// ECMA 262 - 15.9.5.41
612function DateSetUTCFullYear(year, month, date) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100613 var t = UTC_DATE_VALUE(this);
Ben Murdoch85b71792012-04-11 18:30:58 +0100614 year = ToNumber(year);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100615 var argc = %_ArgumentsLength();
616 var time ;
617 if (NUMBER_IS_NAN(t)) {
618 month = argc < 2 ? 0 : ToNumber(month);
619 date = argc < 3 ? 1 : ToNumber(date);
620 time = 0;
621 } else {
622 month = argc < 2 ? UTC_MONTH(this) : ToNumber(month);
623 date = argc < 3 ? UTC_DAY(this) : ToNumber(date);
624 time = UTC_TIME_IN_DAY(this);
625 }
Andrei Popescu31002712010-02-23 13:46:05 +0000626 var day = MakeDay(year, month, date);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100627 return SET_UTC_DATE_VALUE(this, MakeDate(day, time));
Andrei Popescu31002712010-02-23 13:46:05 +0000628}
629
630
631// ECMA 262 - 15.9.5.42
632function DateToUTCString() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100633 var t = UTC_DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000634 if (NUMBER_IS_NAN(t)) return kInvalidDate;
635 // Return UTC string of the form: Sat, 31 Jan 1970 23:00:00 GMT
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100636 return WeekDays[UTC_WEEKDAY(this)] + ', '
637 + TwoDigitString(UTC_DAY(this)) + ' '
638 + Months[UTC_MONTH(this)] + ' '
639 + UTC_YEAR(this) + ' '
640 + TimeStringUTC(this) + ' GMT';
Andrei Popescu31002712010-02-23 13:46:05 +0000641}
642
643
644// ECMA 262 - B.2.4
645function DateGetYear() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100646 return LOCAL_YEAR(this) - 1900;
Andrei Popescu31002712010-02-23 13:46:05 +0000647}
648
649
650// ECMA 262 - B.2.5
651function DateSetYear(year) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100652 CHECK_DATE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000653 year = ToNumber(year);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000654 if (NUMBER_IS_NAN(year)) return SET_UTC_DATE_VALUE(this, NAN);
Andrei Popescu31002712010-02-23 13:46:05 +0000655 year = (0 <= TO_INTEGER(year) && TO_INTEGER(year) <= 99)
656 ? 1900 + TO_INTEGER(year) : year;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100657 var t = LOCAL_DATE_VALUE(this);
658 var month, date, time;
659 if (NUMBER_IS_NAN(t)) {
660 month = 0;
661 date = 1;
662 time = 0;
663 } else {
664 month = LOCAL_MONTH(this);
665 date = LOCAL_DAY(this);
666 time = LOCAL_TIME_IN_DAY(this);
667 }
668 var day = MakeDay(year, month, date);
669 return SET_LOCAL_DATE_VALUE(this, MakeDate(day, time));
Andrei Popescu31002712010-02-23 13:46:05 +0000670}
671
672
673// ECMA 262 - B.2.6
674//
675// Notice that this does not follow ECMA 262 completely. ECMA 262
676// says that toGMTString should be the same Function object as
677// toUTCString. JSC does not do this, so for compatibility we do not
678// do that either. Instead, we create a new function whose name
679// property will return toGMTString.
680function DateToGMTString() {
Steve Block1e0659c2011-05-24 12:43:12 +0100681 return %_CallFunction(this, DateToUTCString);
Andrei Popescu31002712010-02-23 13:46:05 +0000682}
683
684
685function PadInt(n, digits) {
686 if (digits == 1) return n;
687 return n < MathPow(10, digits - 1) ? '0' + PadInt(n, digits - 1) : n;
688}
689
690
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100691// ECMA 262 - 15.9.5.43
Andrei Popescu31002712010-02-23 13:46:05 +0000692function DateToISOString() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100693 var t = UTC_DATE_VALUE(this);
694 if (NUMBER_IS_NAN(t)) throw MakeRangeError("invalid_time_value", []);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000695 var year = this.getUTCFullYear();
696 var year_string;
697 if (year >= 0 && year <= 9999) {
698 year_string = PadInt(year, 4);
699 } else {
700 if (year < 0) {
701 year_string = "-" + PadInt(-year, 6);
702 } else {
703 year_string = "+" + PadInt(year, 6);
704 }
705 }
706 return year_string +
Ben Murdochb0fe1622011-05-05 13:52:32 +0100707 '-' + PadInt(this.getUTCMonth() + 1, 2) +
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000708 '-' + PadInt(this.getUTCDate(), 2) +
Ben Murdochb0fe1622011-05-05 13:52:32 +0100709 'T' + PadInt(this.getUTCHours(), 2) +
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000710 ':' + PadInt(this.getUTCMinutes(), 2) +
Ben Murdochb0fe1622011-05-05 13:52:32 +0100711 ':' + PadInt(this.getUTCSeconds(), 2) +
Andrei Popescu31002712010-02-23 13:46:05 +0000712 '.' + PadInt(this.getUTCMilliseconds(), 3) +
713 'Z';
714}
715
716
717function DateToJSON(key) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100718 var o = ToObject(this);
719 var tv = DefaultNumber(o);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000720 if (IS_NUMBER(tv) && !NUMBER_IS_FINITE(tv)) {
721 return null;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100722 }
723 return o.toISOString();
724}
725
726
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000727var date_cache_version_holder;
728var date_cache_version = NAN;
729
730
731function CheckDateCacheCurrent() {
732 if (!date_cache_version_holder) {
733 date_cache_version_holder = %DateCacheVersion();
734 }
735 if (date_cache_version_holder[0] == date_cache_version) {
736 return;
737 }
738 date_cache_version = date_cache_version_holder[0];
739
Ben Murdochb0fe1622011-05-05 13:52:32 +0100740 // Reset the timezone cache:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000741 timezone_cache_time = NAN;
742 timezone_cache_timezone = UNDEFINED;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100743
Ben Murdochb0fe1622011-05-05 13:52:32 +0100744 // Reset the date cache:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000745 Date_cache.time = NAN;
746 Date_cache.string = null;
Andrei Popescu31002712010-02-23 13:46:05 +0000747}
748
749
750// -------------------------------------------------------------------
751
Ben Murdoch589d6972011-11-30 16:04:58 +0000752function SetUpDate() {
753 %CheckIsBootstrapping();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000754
755 %SetCode($Date, DateConstructor);
756 %FunctionSetPrototype($Date, new $Date(NAN));
757
Ben Murdoch589d6972011-11-30 16:04:58 +0000758 // Set up non-enumerable properties of the Date object itself.
Andrei Popescu31002712010-02-23 13:46:05 +0000759 InstallFunctions($Date, DONT_ENUM, $Array(
760 "UTC", DateUTC,
761 "parse", DateParse,
762 "now", DateNow
763 ));
764
Ben Murdoch589d6972011-11-30 16:04:58 +0000765 // Set up non-enumerable constructor property of the Date prototype object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000766 %AddNamedProperty($Date.prototype, "constructor", $Date, DONT_ENUM);
Andrei Popescu31002712010-02-23 13:46:05 +0000767
Ben Murdoch589d6972011-11-30 16:04:58 +0000768 // Set up non-enumerable functions of the Date prototype object and
Andrei Popescu31002712010-02-23 13:46:05 +0000769 // set their names.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100770 InstallFunctions($Date.prototype, DONT_ENUM, $Array(
Andrei Popescu31002712010-02-23 13:46:05 +0000771 "toString", DateToString,
772 "toDateString", DateToDateString,
773 "toTimeString", DateToTimeString,
774 "toLocaleString", DateToLocaleString,
775 "toLocaleDateString", DateToLocaleDateString,
776 "toLocaleTimeString", DateToLocaleTimeString,
777 "valueOf", DateValueOf,
778 "getTime", DateGetTime,
779 "getFullYear", DateGetFullYear,
780 "getUTCFullYear", DateGetUTCFullYear,
781 "getMonth", DateGetMonth,
782 "getUTCMonth", DateGetUTCMonth,
783 "getDate", DateGetDate,
784 "getUTCDate", DateGetUTCDate,
785 "getDay", DateGetDay,
786 "getUTCDay", DateGetUTCDay,
787 "getHours", DateGetHours,
788 "getUTCHours", DateGetUTCHours,
789 "getMinutes", DateGetMinutes,
790 "getUTCMinutes", DateGetUTCMinutes,
791 "getSeconds", DateGetSeconds,
792 "getUTCSeconds", DateGetUTCSeconds,
793 "getMilliseconds", DateGetMilliseconds,
794 "getUTCMilliseconds", DateGetUTCMilliseconds,
795 "getTimezoneOffset", DateGetTimezoneOffset,
796 "setTime", DateSetTime,
797 "setMilliseconds", DateSetMilliseconds,
798 "setUTCMilliseconds", DateSetUTCMilliseconds,
799 "setSeconds", DateSetSeconds,
800 "setUTCSeconds", DateSetUTCSeconds,
801 "setMinutes", DateSetMinutes,
802 "setUTCMinutes", DateSetUTCMinutes,
803 "setHours", DateSetHours,
804 "setUTCHours", DateSetUTCHours,
805 "setDate", DateSetDate,
806 "setUTCDate", DateSetUTCDate,
807 "setMonth", DateSetMonth,
808 "setUTCMonth", DateSetUTCMonth,
809 "setFullYear", DateSetFullYear,
810 "setUTCFullYear", DateSetUTCFullYear,
811 "toGMTString", DateToGMTString,
812 "toUTCString", DateToUTCString,
813 "getYear", DateGetYear,
814 "setYear", DateSetYear,
815 "toISOString", DateToISOString,
816 "toJSON", DateToJSON
817 ));
818}
819
Ben Murdoch589d6972011-11-30 16:04:58 +0000820SetUpDate();