Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(74)

Side by Side Diff: src/date.js

Issue 9572008: Implement date library functions in C++. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Bug fixes. Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 26 matching lines...) Expand all
37 // Keep reference to original values of some global properties. This 37 // Keep reference to original values of some global properties. This
38 // has the added benefit that the code in this file is isolated from 38 // has the added benefit that the code in this file is isolated from
39 // changes to these properties. 39 // changes to these properties.
40 var $Date = global.Date; 40 var $Date = global.Date;
41 41
42 // Helper function to throw error. 42 // Helper function to throw error.
43 function ThrowDateTypeError() { 43 function ThrowDateTypeError() {
44 throw new $TypeError('this is not a Date object.'); 44 throw new $TypeError('this is not a Date object.');
45 } 45 }
46 46
47 // ECMA 262 - 5.2
48 function Modulo(value, remainder) {
49 var mod = value % remainder;
50 // Guard against returning -0.
51 if (mod == 0) return 0;
52 return mod >= 0 ? mod : mod + remainder;
53 }
54
55
56 function TimeWithinDay(time) {
57 return Modulo(time, msPerDay);
58 }
59
60
61 // ECMA 262 - 15.9.1.3
62 function DaysInYear(year) {
63 if (year % 4 != 0) return 365;
64 if ((year % 100 == 0) && (year % 400 != 0)) return 365;
65 return 366;
66 }
67
68
69 function DayFromYear(year) {
70 return 365 * (year-1970)
71 + FLOOR((year-1969)/4)
72 - FLOOR((year-1901)/100)
73 + FLOOR((year-1601)/400);
74 }
75
76
77 function TimeFromYear(year) {
78 return msPerDay * DayFromYear(year);
79 }
80
81
82 function InLeapYear(time) {
83 return DaysInYear(YearFromTime(time)) - 365; // Returns 1 or 0.
84 }
85
86
87 // ECMA 262 - 15.9.1.9
88 function EquivalentYear(year) {
89 // Returns an equivalent year in the range [2008-2035] matching
90 // - leap year.
91 // - week day of first day.
92 var time = TimeFromYear(year);
93 var recent_year = (InLeapYear(time) == 0 ? 1967 : 1956) +
94 (WeekDay(time) * 12) % 28;
95 // Find the year in the range 2008..2037 that is equivalent mod 28.
96 // Add 3*28 to give a positive argument to the modulus operator.
97 return 2008 + (recent_year + 3*28 - 2008) % 28;
98 }
99
100
101 function EquivalentTime(t) {
102 // The issue here is that some library calls don't work right for dates
103 // that cannot be represented using a non-negative signed 32 bit integer
104 // (measured in whole seconds based on the 1970 epoch).
105 // We solve this by mapping the time to a year with same leap-year-ness
106 // and same starting day for the year. The ECMAscript specification says
107 // we must do this, but for compatibility with other browsers, we use
108 // the actual year if it is in the range 1970..2037
109 if (t >= 0 && t <= 2.1e12) return t;
110
111 var day = MakeDay(EquivalentYear(YearFromTime(t)),
112 MonthFromTime(t),
113 DateFromTime(t));
114 return MakeDate(day, TimeWithinDay(t));
115 }
116
117
118 // local_time_offset is initialized when the DST_offset_cache is missed.
119 // It must not be used until after a call to DaylightSavingsOffset().
120 // In this way, only one check, for a DST cache miss, is needed.
121 var local_time_offset;
122
123
124 // Because computing the DST offset is an expensive operation,
125 // we keep a cache of the last computed DST offset along with a time interval
126 // where we know the cache is valid.
127 // When the cache is valid, local_time_offset is also valid.
128 var DST_offset_cache = {
129 // Cached DST offset.
130 offset: 0,
131 // Time interval where the cached offset is valid.
132 start: 0, end: -1,
133 // Size of next interval expansion.
134 increment: 0,
135 initial_increment: 19 * msPerDay
136 };
137
138
139 // NOTE: The implementation relies on the fact that no time zones have
140 // more than one daylight savings offset change per 19 days.
141 //
142 // In Egypt in 2010 they decided to suspend DST during Ramadan. This
143 // led to a short interval where DST is in effect from September 10 to
144 // September 30.
145 //
146 // If this function is called with NaN it returns NaN.
147 function DaylightSavingsOffset(t) {
148 // Load the cache object from the builtins object.
149 var cache = DST_offset_cache;
150
151 // Cache the start and the end in local variables for fast access.
152 var start = cache.start;
153 var end = cache.end;
154
155 if (start <= t) {
156 // If the time fits in the cached interval, return the cached offset.
157 if (t <= end) return cache.offset;
158
159 // If the cache misses, the local_time_offset may not be initialized.
160 if (IS_UNDEFINED(local_time_offset)) {
161 local_time_offset = %DateLocalTimeOffset();
162 }
163
164 // Compute a possible new interval end.
165 var new_end = end + cache.increment;
166
167 if (t <= new_end) {
168 var end_offset = %DateDaylightSavingsOffset(EquivalentTime(new_end));
169 if (cache.offset == end_offset) {
170 // If the offset at the end of the new interval still matches
171 // the offset in the cache, we grow the cached time interval
172 // and return the offset.
173 cache.end = new_end;
174 cache.increment = cache.initial_increment;
175 return end_offset;
176 } else {
177 var offset = %DateDaylightSavingsOffset(EquivalentTime(t));
178 if (offset == end_offset) {
179 // The offset at the given time is equal to the offset at the
180 // new end of the interval, so that means that we've just skipped
181 // the point in time where the DST offset change occurred. Updated
182 // the interval to reflect this and reset the increment.
183 cache.start = t;
184 cache.end = new_end;
185 cache.increment = cache.initial_increment;
186 } else {
187 // The interval contains a DST offset change and the given time is
188 // before it. Adjust the increment to avoid a linear search for
189 // the offset change point and change the end of the interval.
190 cache.increment /= 3;
191 cache.end = t;
192 }
193 // Update the offset in the cache and return it.
194 cache.offset = offset;
195 return offset;
196 }
197 }
198 }
199
200 // If the cache misses, the local_time_offset may not be initialized.
201 if (IS_UNDEFINED(local_time_offset)) {
202 local_time_offset = %DateLocalTimeOffset();
203 }
204 // Compute the DST offset for the time and shrink the cache interval
205 // to only contain the time. This allows fast repeated DST offset
206 // computations for the same time.
207 var offset = %DateDaylightSavingsOffset(EquivalentTime(t));
208 cache.offset = offset;
209 cache.start = cache.end = t;
210 cache.increment = cache.initial_increment;
211 return offset;
212 }
213
214 47
215 var timezone_cache_time = $NaN; 48 var timezone_cache_time = $NaN;
216 var timezone_cache_timezone; 49 var timezone_cache_timezone;
217 50
218 function LocalTimezone(t) { 51 function LocalTimezone(t) {
219 if (NUMBER_IS_NAN(t)) return ""; 52 if (NUMBER_IS_NAN(t)) return "";
220 if (t == timezone_cache_time) { 53 if (t == timezone_cache_time) {
221 return timezone_cache_timezone; 54 return timezone_cache_timezone;
222 } 55 }
223 var timezone = %DateLocalTimezone(EquivalentTime(t)); 56 var timezone = %DateLocalTimezone(t);
224 timezone_cache_time = t; 57 timezone_cache_time = t;
225 timezone_cache_timezone = timezone; 58 timezone_cache_timezone = timezone;
226 return timezone; 59 return timezone;
227 } 60 }
228 61
229 62
230 function WeekDay(time) {
231 return Modulo(DAY(time) + 4, 7);
232 }
233
234
235 function LocalTime(time) {
236 if (NUMBER_IS_NAN(time)) return time;
237 // DaylightSavingsOffset called before local_time_offset used.
238 return time + DaylightSavingsOffset(time) + local_time_offset;
239 }
240
241
242 var ltcache = {
243 key: null,
244 val: null
245 };
246
247 function LocalTimeNoCheck(time) {
248 var ltc = ltcache;
249 if (%_ObjectEquals(time, ltc.key)) return ltc.val;
250
251 // Inline the DST offset cache checks for speed.
252 // The cache is hit, or DaylightSavingsOffset is called,
253 // before local_time_offset is used.
254 var cache = DST_offset_cache;
255 if (cache.start <= time && time <= cache.end) {
256 var dst_offset = cache.offset;
257 } else {
258 var dst_offset = DaylightSavingsOffset(time);
259 }
260 ltc.key = time;
261 return (ltc.val = time + local_time_offset + dst_offset);
262 }
263
264
265 function UTC(time) { 63 function UTC(time) {
266 if (NUMBER_IS_NAN(time)) return time; 64 if (NUMBER_IS_NAN(time)) return time;
267 // local_time_offset is needed before the call to DaylightSavingsOffset, 65 // local_time_offset is needed before the call to DaylightSavingsOffset,
268 // so it may be uninitialized. 66 // so it may be uninitialized.
269 if (IS_UNDEFINED(local_time_offset)) { 67 return %DateToUTC(time);
270 local_time_offset = %DateLocalTimeOffset();
271 }
272 var tmp = time - local_time_offset;
273 return tmp - DaylightSavingsOffset(tmp);
274 } 68 }
275 69
276 70
277 // ECMA 262 - 15.9.1.11 71 // ECMA 262 - 15.9.1.11
278 function MakeTime(hour, min, sec, ms) { 72 function MakeTime(hour, min, sec, ms) {
279 if (!$isFinite(hour)) return $NaN; 73 if (!$isFinite(hour)) return $NaN;
280 if (!$isFinite(min)) return $NaN; 74 if (!$isFinite(min)) return $NaN;
281 if (!$isFinite(sec)) return $NaN; 75 if (!$isFinite(sec)) return $NaN;
282 if (!$isFinite(ms)) return $NaN; 76 if (!$isFinite(ms)) return $NaN;
283 return TO_INTEGER(hour) * msPerHour 77 return TO_INTEGER(hour) * msPerHour
284 + TO_INTEGER(min) * msPerMinute 78 + TO_INTEGER(min) * msPerMinute
285 + TO_INTEGER(sec) * msPerSecond 79 + TO_INTEGER(sec) * msPerSecond
286 + TO_INTEGER(ms); 80 + TO_INTEGER(ms);
287 } 81 }
288 82
289 83
290 // ECMA 262 - 15.9.1.12 84 // ECMA 262 - 15.9.1.12
291 function TimeInYear(year) { 85 function TimeInYear(year) {
292 return DaysInYear(year) * msPerDay; 86 return DaysInYear(year) * msPerDay;
293 } 87 }
294 88
295 89
296 var ymd_from_time_cache = [1970, 0, 1];
297 var ymd_from_time_cached_time = 0;
298
299 function YearFromTime(t) {
300 if (t !== ymd_from_time_cached_time) {
301 if (!$isFinite(t)) {
302 return $NaN;
303 }
304
305 %DateYMDFromTime(t, ymd_from_time_cache);
306 ymd_from_time_cached_time = t;
307 }
308
309 return ymd_from_time_cache[0];
310 }
311
312 function MonthFromTime(t) {
313 if (t !== ymd_from_time_cached_time) {
314 if (!$isFinite(t)) {
315 return $NaN;
316 }
317 %DateYMDFromTime(t, ymd_from_time_cache);
318 ymd_from_time_cached_time = t;
319 }
320
321 return ymd_from_time_cache[1];
322 }
323
324 function DateFromTime(t) {
325 if (t !== ymd_from_time_cached_time) {
326 if (!$isFinite(t)) {
327 return $NaN;
328 }
329
330 %DateYMDFromTime(t, ymd_from_time_cache);
331 ymd_from_time_cached_time = t;
332 }
333
334 return ymd_from_time_cache[2];
335 }
336
337
338 // Compute number of days given a year, month, date. 90 // Compute number of days given a year, month, date.
339 // Note that month and date can lie outside the normal range. 91 // Note that month and date can lie outside the normal range.
340 // For example: 92 // For example:
341 // MakeDay(2007, -4, 20) --> MakeDay(2006, 8, 20) 93 // MakeDay(2007, -4, 20) --> MakeDay(2006, 8, 20)
342 // MakeDay(2007, -33, 1) --> MakeDay(2004, 3, 1) 94 // MakeDay(2007, -33, 1) --> MakeDay(2004, 3, 1)
343 // MakeDay(2007, 14, -50) --> MakeDay(2007, 8, 11) 95 // MakeDay(2007, 14, -50) --> MakeDay(2007, 8, 11)
344 function MakeDay(year, month, date) { 96 function MakeDay(year, month, date) {
345 if (!$isFinite(year) || !$isFinite(month) || !$isFinite(date)) return $NaN; 97 if (!$isFinite(year) || !$isFinite(month) || !$isFinite(date)) return $NaN;
346 98
347 // Convert to integer and map -0 to 0. 99 // Convert to integer and map -0 to 0.
(...skipping 30 matching lines...) Expand all
378 if ($abs(time) > MAX_TIME_MS) return $NaN; 130 if ($abs(time) > MAX_TIME_MS) return $NaN;
379 return TO_INTEGER(time); 131 return TO_INTEGER(time);
380 } 132 }
381 133
382 134
383 // The Date cache is used to limit the cost of parsing the same Date 135 // The Date cache is used to limit the cost of parsing the same Date
384 // strings over and over again. 136 // strings over and over again.
385 var Date_cache = { 137 var Date_cache = {
386 // Cached time value. 138 // Cached time value.
387 time: $NaN, 139 time: $NaN,
388 // Cached year when interpreting the time as a local time. Only
389 // valid when the time matches cached time.
390 year: $NaN,
391 // String input for which the cached time is valid. 140 // String input for which the cached time is valid.
392 string: null 141 string: null
393 }; 142 };
394 143
395 144
396 %SetCode($Date, function(year, month, date, hours, minutes, seconds, ms) { 145 %SetCode($Date, function(year, month, date, hours, minutes, seconds, ms) {
397 if (!%_IsConstructCall()) { 146 if (!%_IsConstructCall()) {
398 // ECMA 262 - 15.9.2 147 // ECMA 262 - 15.9.2
399 return (new $Date()).toString(); 148 return (new $Date()).toString();
400 } 149 }
401 150
402 // ECMA 262 - 15.9.3 151 // ECMA 262 - 15.9.3
403 var argc = %_ArgumentsLength(); 152 var argc = %_ArgumentsLength();
404 var value; 153 var value;
405 if (argc == 0) { 154 if (argc == 0) {
406 value = %DateCurrentTime(); 155 value = %DateCurrentTime();
407 156 SET_UTC_DATE_VALUE(this, value);
408 } else if (argc == 1) { 157 } else if (argc == 1) {
409 if (IS_NUMBER(year)) { 158 if (IS_NUMBER(year)) {
410 value = TimeClip(year); 159 value = year;
411
412 } else if (IS_STRING(year)) { 160 } else if (IS_STRING(year)) {
413 // Probe the Date cache. If we already have a time value for the 161 // Probe the Date cache. If we already have a time value for the
414 // given time, we re-use that instead of parsing the string again. 162 // given time, we re-use that instead of parsing the string again.
415 var cache = Date_cache; 163 var cache = Date_cache;
416 if (cache.string === year) { 164 if (cache.string === year) {
417 value = cache.time; 165 value = cache.time;
418 } else { 166 } else {
419 value = DateParse(year); 167 value = DateParse(year);
420 if (!NUMBER_IS_NAN(value)) { 168 if (!NUMBER_IS_NAN(value)) {
421 cache.time = value; 169 cache.time = value;
422 cache.year = YearFromTime(LocalTimeNoCheck(value));
423 cache.string = year; 170 cache.string = year;
424 } 171 }
425 } 172 }
426 173
427 } else { 174 } else {
428 // According to ECMA 262, no hint should be given for this 175 // According to ECMA 262, no hint should be given for this
429 // conversion. However, ToPrimitive defaults to STRING_HINT for 176 // conversion. However, ToPrimitive defaults to STRING_HINT for
430 // Date objects which will lose precision when the Date 177 // Date objects which will lose precision when the Date
431 // constructor is called with another Date object as its 178 // constructor is called with another Date object as its
432 // argument. We therefore use NUMBER_HINT for the conversion, 179 // argument. We therefore use NUMBER_HINT for the conversion,
433 // which is the default for everything else than Date objects. 180 // which is the default for everything else than Date objects.
434 // This makes us behave like KJS and SpiderMonkey. 181 // This makes us behave like KJS and SpiderMonkey.
435 var time = ToPrimitive(year, NUMBER_HINT); 182 var time = ToPrimitive(year, NUMBER_HINT);
436 value = IS_STRING(time) ? DateParse(time) : TimeClip(ToNumber(time)); 183 value = IS_STRING(time) ? DateParse(time) : ToNumber(time);
437 } 184 }
438 185 SET_UTC_DATE_VALUE(this, value);
439 } else { 186 } else {
440 year = ToNumber(year); 187 year = ToNumber(year);
441 month = ToNumber(month); 188 month = ToNumber(month);
442 date = argc > 2 ? ToNumber(date) : 1; 189 date = argc > 2 ? ToNumber(date) : 1;
443 hours = argc > 3 ? ToNumber(hours) : 0; 190 hours = argc > 3 ? ToNumber(hours) : 0;
444 minutes = argc > 4 ? ToNumber(minutes) : 0; 191 minutes = argc > 4 ? ToNumber(minutes) : 0;
445 seconds = argc > 5 ? ToNumber(seconds) : 0; 192 seconds = argc > 5 ? ToNumber(seconds) : 0;
446 ms = argc > 6 ? ToNumber(ms) : 0; 193 ms = argc > 6 ? ToNumber(ms) : 0;
447 year = (!NUMBER_IS_NAN(year) && 194 year = (!NUMBER_IS_NAN(year) &&
448 0 <= TO_INTEGER(year) && 195 0 <= TO_INTEGER(year) &&
449 TO_INTEGER(year) <= 99) ? 1900 + TO_INTEGER(year) : year; 196 TO_INTEGER(year) <= 99) ? 1900 + TO_INTEGER(year) : year;
450 var day = MakeDay(year, month, date); 197 var day = MakeDay(year, month, date);
451 var time = MakeTime(hours, minutes, seconds, ms); 198 var time = MakeTime(hours, minutes, seconds, ms);
452 value = TimeClip(UTC(MakeDate(day, time))); 199 value = MakeDate(day, time);
200 SET_LOCAL_DATE_VALUE(this, value);
453 } 201 }
454 %_SetValueOf(this, value);
455 }); 202 });
456 203
457 204
458 %FunctionSetPrototype($Date, new $Date($NaN)); 205 %FunctionSetPrototype($Date, new $Date($NaN));
459 206
460 207
461 var WeekDays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; 208 var WeekDays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
462 var Months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 209 var Months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
463 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; 210 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
464 211
465 212
466 function TwoDigitString(value) { 213 function TwoDigitString(value) {
467 return value < 10 ? "0" + value : "" + value; 214 return value < 10 ? "0" + value : "" + value;
468 } 215 }
469 216
470 217
471 function DateString(time) { 218 function DateString(date) {
472 return WeekDays[WeekDay(time)] + ' ' 219 return WeekDays[LOCAL_WEEKDAY(date)] + ' '
473 + Months[MonthFromTime(time)] + ' ' 220 + Months[LOCAL_MONTH(date)] + ' '
474 + TwoDigitString(DateFromTime(time)) + ' ' 221 + TwoDigitString(LOCAL_DAY(date)) + ' '
475 + YearFromTime(time); 222 + LOCAL_YEAR(date);
476 } 223 }
477 224
478 225
479 var LongWeekDays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 226 var LongWeekDays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday',
480 'Thursday', 'Friday', 'Saturday']; 227 'Thursday', 'Friday', 'Saturday'];
481 var LongMonths = ['January', 'February', 'March', 'April', 'May', 'June', 228 var LongMonths = ['January', 'February', 'March', 'April', 'May', 'June',
482 'July', 'August', 'September', 'October', 'November', 'December']; 229 'July', 'August', 'September', 'October', 'November', 'December'];
483 230
484 231
485 function LongDateString(time) { 232 function LongDateString(date) {
486 return LongWeekDays[WeekDay(time)] + ', ' 233 return LongWeekDays[LOCAL_WEEKDAY(date)] + ', '
487 + LongMonths[MonthFromTime(time)] + ' ' 234 + LongMonths[LOCAL_MONTH(date)] + ' '
488 + TwoDigitString(DateFromTime(time)) + ', ' 235 + TwoDigitString(LOCAL_DAY(date)) + ', '
489 + YearFromTime(time); 236 + LOCAL_YEAR(date);
490 } 237 }
491 238
492 239
493 function TimeString(time) { 240 function TimeString(date) {
494 return TwoDigitString(HOUR_FROM_TIME(time)) + ':' 241 return TwoDigitString(LOCAL_HOUR(date)) + ':'
495 + TwoDigitString(MIN_FROM_TIME(time)) + ':' 242 + TwoDigitString(LOCAL_MIN(date)) + ':'
496 + TwoDigitString(SEC_FROM_TIME(time)); 243 + TwoDigitString(LOCAL_SEC(date));
497 } 244 }
498 245
499 246
500 function LocalTimezoneString(time) { 247 function TimeStringUTC(date) {
rossberg 2012/03/06 15:55:50 Hm, this does three calls into the runtime. But I
ulan 2012/03/07 10:55:21 An alternative would be to get the time in day and
501 var old_timezone = timezone_cache_timezone; 248 return TwoDigitString(UTC_HOUR(date)) + ':'
502 var timezone = LocalTimezone(time); 249 + TwoDigitString(UTC_MIN(date)) + ':'
503 if (old_timezone && timezone != old_timezone) { 250 + TwoDigitString(UTC_SEC(date));
504 // If the timezone string has changed from the one that we cached, 251 }
505 // the local time offset may now be wrong. So we need to update it
506 // and try again.
507 local_time_offset = %DateLocalTimeOffset();
508 // We also need to invalidate the DST cache as the new timezone may have
509 // different DST times.
510 var dst_cache = DST_offset_cache;
511 dst_cache.start = 0;
512 dst_cache.end = -1;
513 }
514 252
515 var timezoneOffset = 253
516 (DaylightSavingsOffset(time) + local_time_offset) / msPerMinute; 254 function LocalTimezoneString(date) {
255 var timezone = LocalTimezone(UTC_DATE_VALUE(date));
256
257 var timezoneOffset = -TIMEZONE_OFFSET(date);
517 var sign = (timezoneOffset >= 0) ? 1 : -1; 258 var sign = (timezoneOffset >= 0) ? 1 : -1;
518 var hours = FLOOR((sign * timezoneOffset)/60); 259 var hours = FLOOR((sign * timezoneOffset)/60);
519 var min = FLOOR((sign * timezoneOffset)%60); 260 var min = FLOOR((sign * timezoneOffset)%60);
520 var gmt = ' GMT' + ((sign == 1) ? '+' : '-') + 261 var gmt = ' GMT' + ((sign == 1) ? '+' : '-') +
521 TwoDigitString(hours) + TwoDigitString(min); 262 TwoDigitString(hours) + TwoDigitString(min);
522 return gmt + ' (' + timezone + ')'; 263 return gmt + ' (' + timezone + ')';
523 } 264 }
524 265
525 266
526 function DatePrintString(time) { 267 function DatePrintString(date) {
527 return DateString(time) + ' ' + TimeString(time); 268 return DateString(date) + ' ' + TimeString(date);
528 } 269 }
529 270
530 // ------------------------------------------------------------------- 271 // -------------------------------------------------------------------
531 272
532 // Reused output buffer. Used when parsing date strings. 273 // Reused output buffer. Used when parsing date strings.
533 var parse_buffer = $Array(8); 274 var parse_buffer = $Array(8);
534 275
535 // ECMA 262 - 15.9.4.2 276 // ECMA 262 - 15.9.4.2
536 function DateParse(string) { 277 function DateParse(string) {
537 var arr = %DateParseString(ToString(string), parse_buffer); 278 var arr = %DateParseString(ToString(string), parse_buffer);
(...skipping 19 matching lines...) Expand all
557 date = argc > 2 ? ToNumber(date) : 1; 298 date = argc > 2 ? ToNumber(date) : 1;
558 hours = argc > 3 ? ToNumber(hours) : 0; 299 hours = argc > 3 ? ToNumber(hours) : 0;
559 minutes = argc > 4 ? ToNumber(minutes) : 0; 300 minutes = argc > 4 ? ToNumber(minutes) : 0;
560 seconds = argc > 5 ? ToNumber(seconds) : 0; 301 seconds = argc > 5 ? ToNumber(seconds) : 0;
561 ms = argc > 6 ? ToNumber(ms) : 0; 302 ms = argc > 6 ? ToNumber(ms) : 0;
562 year = (!NUMBER_IS_NAN(year) && 303 year = (!NUMBER_IS_NAN(year) &&
563 0 <= TO_INTEGER(year) && 304 0 <= TO_INTEGER(year) &&
564 TO_INTEGER(year) <= 99) ? 1900 + TO_INTEGER(year) : year; 305 TO_INTEGER(year) <= 99) ? 1900 + TO_INTEGER(year) : year;
565 var day = MakeDay(year, month, date); 306 var day = MakeDay(year, month, date);
566 var time = MakeTime(hours, minutes, seconds, ms); 307 var time = MakeTime(hours, minutes, seconds, ms);
567 return %_SetValueOf(this, TimeClip(MakeDate(day, time))); 308 return TimeClip(MakeDate(day, time));
568 } 309 }
569 310
570 311
571 // Mozilla-specific extension. Returns the number of milliseconds 312 // Mozilla-specific extension. Returns the number of milliseconds
572 // elapsed since 1 January 1970 00:00:00 UTC. 313 // elapsed since 1 January 1970 00:00:00 UTC.
573 function DateNow() { 314 function DateNow() {
574 return %DateCurrentTime(); 315 return %DateCurrentTime();
575 } 316 }
576 317
577 318
578 // ECMA 262 - 15.9.5.2 319 // ECMA 262 - 15.9.5.2
579 function DateToString() { 320 function DateToString() {
580 var t = DATE_VALUE(this); 321 CHECK_DATE(this);
322 var t = UTC_DATE_VALUE(this)
581 if (NUMBER_IS_NAN(t)) return kInvalidDate; 323 if (NUMBER_IS_NAN(t)) return kInvalidDate;
582 var time_zone_string = LocalTimezoneString(t); // May update local offset. 324 var time_zone_string = LocalTimezoneString(this)
583 return DatePrintString(LocalTimeNoCheck(t)) + time_zone_string; 325 return DatePrintString(this) + time_zone_string;
584 } 326 }
585 327
586 328
587 // ECMA 262 - 15.9.5.3 329 // ECMA 262 - 15.9.5.3
588 function DateToDateString() { 330 function DateToDateString() {
589 var t = DATE_VALUE(this); 331 CHECK_DATE(this);
332 var t = UTC_DATE_VALUE(this);
590 if (NUMBER_IS_NAN(t)) return kInvalidDate; 333 if (NUMBER_IS_NAN(t)) return kInvalidDate;
591 return DateString(LocalTimeNoCheck(t)); 334 return DateString(this);
592 } 335 }
593 336
594 337
595 // ECMA 262 - 15.9.5.4 338 // ECMA 262 - 15.9.5.4
596 function DateToTimeString() { 339 function DateToTimeString() {
597 var t = DATE_VALUE(this); 340 CHECK_DATE(this);
341 var t = UTC_DATE_VALUE(this);
598 if (NUMBER_IS_NAN(t)) return kInvalidDate; 342 if (NUMBER_IS_NAN(t)) return kInvalidDate;
599 var time_zone_string = LocalTimezoneString(t); // May update local offset. 343 var time_zone_string = LocalTimezoneString(this);
600 return TimeString(LocalTimeNoCheck(t)) + time_zone_string; 344 return TimeString(this) + time_zone_string;
601 } 345 }
602 346
603 347
604 // ECMA 262 - 15.9.5.5 348 // ECMA 262 - 15.9.5.5
605 function DateToLocaleString() { 349 function DateToLocaleString() {
606 return %_CallFunction(this, DateToString); 350 return %_CallFunction(this, DateToString);
607 } 351 }
608 352
609 353
610 // ECMA 262 - 15.9.5.6 354 // ECMA 262 - 15.9.5.6
611 function DateToLocaleDateString() { 355 function DateToLocaleDateString() {
612 var t = DATE_VALUE(this); 356 CHECK_DATE(this);
357 var t = UTC_DATE_VALUE(this);
613 if (NUMBER_IS_NAN(t)) return kInvalidDate; 358 if (NUMBER_IS_NAN(t)) return kInvalidDate;
614 return LongDateString(LocalTimeNoCheck(t)); 359 return LongDateString(this);
615 } 360 }
616 361
617 362
618 // ECMA 262 - 15.9.5.7 363 // ECMA 262 - 15.9.5.7
619 function DateToLocaleTimeString() { 364 function DateToLocaleTimeString() {
620 var t = DATE_VALUE(this); 365 CHECK_DATE(this);
366 var t = UTC_DATE_VALUE(this);
621 if (NUMBER_IS_NAN(t)) return kInvalidDate; 367 if (NUMBER_IS_NAN(t)) return kInvalidDate;
622 var lt = LocalTimeNoCheck(t); 368 return TimeString(this);
623 return TimeString(lt);
624 } 369 }
625 370
626 371
627 // ECMA 262 - 15.9.5.8 372 // ECMA 262 - 15.9.5.8
628 function DateValueOf() { 373 function DateValueOf() {
629 return DATE_VALUE(this); 374 CHECK_DATE(this);
375 return UTC_DATE_VALUE(this);
630 } 376 }
631 377
632 378
633 // ECMA 262 - 15.9.5.9 379 // ECMA 262 - 15.9.5.9
634 function DateGetTime() { 380 function DateGetTime() {
635 return DATE_VALUE(this); 381 CHECK_DATE(this);
382 return UTC_DATE_VALUE(this);
636 } 383 }
637 384
638 385
639 // ECMA 262 - 15.9.5.10 386 // ECMA 262 - 15.9.5.10
640 function DateGetFullYear() { 387 function DateGetFullYear() {
641 var t = DATE_VALUE(this); 388 CHECK_DATE(this);
642 if (NUMBER_IS_NAN(t)) return t; 389 return LOCAL_YEAR(this);
643 var cache = Date_cache;
644 if (cache.time === t) return cache.year;
645 return YearFromTime(LocalTimeNoCheck(t));
646 } 390 }
647 391
648 392
649 // ECMA 262 - 15.9.5.11 393 // ECMA 262 - 15.9.5.11
650 function DateGetUTCFullYear() { 394 function DateGetUTCFullYear() {
651 var t = DATE_VALUE(this); 395 CHECK_DATE(this);
652 if (NUMBER_IS_NAN(t)) return t; 396 return UTC_YEAR(this);
653 return YearFromTime(t);
654 } 397 }
655 398
656 399
657 // ECMA 262 - 15.9.5.12 400 // ECMA 262 - 15.9.5.12
658 function DateGetMonth() { 401 function DateGetMonth() {
659 var t = DATE_VALUE(this); 402 CHECK_DATE(this);
660 if (NUMBER_IS_NAN(t)) return t; 403 return LOCAL_MONTH(this);
661 return MonthFromTime(LocalTimeNoCheck(t));
662 } 404 }
663 405
664 406
665 // ECMA 262 - 15.9.5.13 407 // ECMA 262 - 15.9.5.13
666 function DateGetUTCMonth() { 408 function DateGetUTCMonth() {
667 var t = DATE_VALUE(this); 409 CHECK_DATE(this);
668 if (NUMBER_IS_NAN(t)) return t; 410 return UTC_MONTH(this);
669 return MonthFromTime(t);
670 } 411 }
671 412
672 413
673 // ECMA 262 - 15.9.5.14 414 // ECMA 262 - 15.9.5.14
674 function DateGetDate() { 415 function DateGetDate() {
675 var t = DATE_VALUE(this); 416 CHECK_DATE(this);
676 if (NUMBER_IS_NAN(t)) return t; 417 return LOCAL_DAY(this);
677 return DateFromTime(LocalTimeNoCheck(t));
678 } 418 }
679 419
680 420
681 // ECMA 262 - 15.9.5.15 421 // ECMA 262 - 15.9.5.15
682 function DateGetUTCDate() { 422 function DateGetUTCDate() {
683 var t = DATE_VALUE(this); 423 CHECK_DATE(this);
684 return NAN_OR_DATE_FROM_TIME(t); 424 return UTC_DAY(this);
685 } 425 }
686 426
687 427
688 // ECMA 262 - 15.9.5.16 428 // ECMA 262 - 15.9.5.16
689 function DateGetDay() { 429 function DateGetDay() {
690 var t = DATE_VALUE(this); 430 CHECK_DATE(this);
691 if (NUMBER_IS_NAN(t)) return t; 431 return LOCAL_WEEKDAY(this);
692 return WeekDay(LocalTimeNoCheck(t));
693 } 432 }
694 433
695 434
696 // ECMA 262 - 15.9.5.17 435 // ECMA 262 - 15.9.5.17
697 function DateGetUTCDay() { 436 function DateGetUTCDay() {
698 var t = DATE_VALUE(this); 437 CHECK_DATE(this);
699 if (NUMBER_IS_NAN(t)) return t; 438 return UTC_WEEKDAY(this);
700 return WeekDay(t);
701 } 439 }
702 440
703 441
704 // ECMA 262 - 15.9.5.18 442 // ECMA 262 - 15.9.5.18
705 function DateGetHours() { 443 function DateGetHours() {
706 var t = DATE_VALUE(this); 444 CHECK_DATE(this);
707 if (NUMBER_IS_NAN(t)) return t; 445 return LOCAL_HOUR(this);
708 return HOUR_FROM_TIME(LocalTimeNoCheck(t));
709 } 446 }
710 447
711 448
712 // ECMA 262 - 15.9.5.19 449 // ECMA 262 - 15.9.5.19
713 function DateGetUTCHours() { 450 function DateGetUTCHours() {
714 var t = DATE_VALUE(this); 451 CHECK_DATE(this);
715 if (NUMBER_IS_NAN(t)) return t; 452 return UTC_HOUR(this);
716 return HOUR_FROM_TIME(t);
717 } 453 }
718 454
719 455
720 // ECMA 262 - 15.9.5.20 456 // ECMA 262 - 15.9.5.20
721 function DateGetMinutes() { 457 function DateGetMinutes() {
722 var t = DATE_VALUE(this); 458 CHECK_DATE(this);
723 if (NUMBER_IS_NAN(t)) return t; 459 return LOCAL_MIN(this);
724 return MIN_FROM_TIME(LocalTimeNoCheck(t));
725 } 460 }
726 461
727 462
728 // ECMA 262 - 15.9.5.21 463 // ECMA 262 - 15.9.5.21
729 function DateGetUTCMinutes() { 464 function DateGetUTCMinutes() {
730 var t = DATE_VALUE(this); 465 CHECK_DATE(this);
731 return NAN_OR_MIN_FROM_TIME(t); 466 return UTC_MIN(this);
732 } 467 }
733 468
734 469
735 // ECMA 262 - 15.9.5.22 470 // ECMA 262 - 15.9.5.22
736 function DateGetSeconds() { 471 function DateGetSeconds() {
737 var t = DATE_VALUE(this); 472 CHECK_DATE(this);
738 if (NUMBER_IS_NAN(t)) return t; 473 return LOCAL_SEC(this);
739 return SEC_FROM_TIME(LocalTimeNoCheck(t));
740 } 474 }
741 475
742 476
743 // ECMA 262 - 15.9.5.23 477 // ECMA 262 - 15.9.5.23
744 function DateGetUTCSeconds() { 478 function DateGetUTCSeconds() {
745 var t = DATE_VALUE(this); 479 CHECK_DATE(this);
746 return NAN_OR_SEC_FROM_TIME(t); 480 return UTC_SEC(this)
747 } 481 }
748 482
749 483
750 // ECMA 262 - 15.9.5.24 484 // ECMA 262 - 15.9.5.24
751 function DateGetMilliseconds() { 485 function DateGetMilliseconds() {
752 var t = DATE_VALUE(this); 486 CHECK_DATE(this);
753 if (NUMBER_IS_NAN(t)) return t; 487 return LOCAL_MS(this);
754 return MS_FROM_TIME(LocalTimeNoCheck(t));
755 } 488 }
756 489
757 490
758 // ECMA 262 - 15.9.5.25 491 // ECMA 262 - 15.9.5.25
759 function DateGetUTCMilliseconds() { 492 function DateGetUTCMilliseconds() {
760 var t = DATE_VALUE(this); 493 CHECK_DATE(this);
761 return NAN_OR_MS_FROM_TIME(t); 494 return UTC_MS(this);
762 } 495 }
763 496
764 497
765 // ECMA 262 - 15.9.5.26 498 // ECMA 262 - 15.9.5.26
766 function DateGetTimezoneOffset() { 499 function DateGetTimezoneOffset() {
767 var t = DATE_VALUE(this); 500 CHECK_DATE(this);
768 if (NUMBER_IS_NAN(t)) return t; 501 return TIMEZONE_OFFSET(this);
769 return (t - LocalTimeNoCheck(t)) / msPerMinute;
770 } 502 }
771 503
772 504
773 // ECMA 262 - 15.9.5.27 505 // ECMA 262 - 15.9.5.27
774 function DateSetTime(ms) { 506 function DateSetTime(ms) {
775 if (!IS_DATE(this)) ThrowDateTypeError(); 507 CHECK_DATE(this);
776 return %_SetValueOf(this, TimeClip(ToNumber(ms))); 508 SET_UTC_DATE_VALUE(this, ToNumber(ms));
509 return UTC_DATE_VALUE(this);
777 } 510 }
778 511
779 512
780 // ECMA 262 - 15.9.5.28 513 // ECMA 262 - 15.9.5.28
781 function DateSetMilliseconds(ms) { 514 function DateSetMilliseconds(ms) {
782 var t = LocalTime(DATE_VALUE(this)); 515 CHECK_DATE(this);
516 var t = LOCAL_DATE_VALUE(this);
783 ms = ToNumber(ms); 517 ms = ToNumber(ms);
784 var time = MakeTime(HOUR_FROM_TIME(t), 518 var time = MakeTime(LOCAL_HOUR(this), LOCAL_MIN(this), LOCAL_SEC(this), ms);
rossberg 2012/03/06 15:55:50 Not for this CL, but I wonder whether this computa
ulan 2012/03/07 10:55:21 Agreed, leaving this for another CL.
785 MIN_FROM_TIME(t), 519 SET_LOCAL_DATE_VALUE(this, MakeDate(LOCAL_DAYS(this), time));
786 SEC_FROM_TIME(t), 520 return this;
787 ms);
788 return %_SetValueOf(this, TimeClip(UTC(MakeDate(DAY(t), time))));
789 } 521 }
790 522
791 523
792 // ECMA 262 - 15.9.5.29 524 // ECMA 262 - 15.9.5.29
793 function DateSetUTCMilliseconds(ms) { 525 function DateSetUTCMilliseconds(ms) {
794 var t = DATE_VALUE(this); 526 CHECK_DATE(this);
527 var t = UTC_DATE_VALUE(this);
795 ms = ToNumber(ms); 528 ms = ToNumber(ms);
796 var time = MakeTime(HOUR_FROM_TIME(t), 529 var time = MakeTime(UTC_HOUR(this),
797 MIN_FROM_TIME(t), 530 UTC_MIN(this),
798 SEC_FROM_TIME(t), 531 UTC_SEC(this),
799 ms); 532 ms);
800 return %_SetValueOf(this, TimeClip(MakeDate(DAY(t), time))); 533 return SET_UTC_DATE_VALUE(this, MakeDate(UTC_DAYS(this), time));
801 } 534 }
802 535
803 536
804 // ECMA 262 - 15.9.5.30 537 // ECMA 262 - 15.9.5.30
805 function DateSetSeconds(sec, ms) { 538 function DateSetSeconds(sec, ms) {
806 var t = LocalTime(DATE_VALUE(this)); 539 CHECK_DATE(this);
540 var t = LOCAL_DATE_VALUE(this);
807 sec = ToNumber(sec); 541 sec = ToNumber(sec);
808 ms = %_ArgumentsLength() < 2 ? NAN_OR_MS_FROM_TIME(t) : ToNumber(ms); 542 ms = %_ArgumentsLength() < 2 ? LOCAL_MS(this) : ToNumber(ms);
809 var time = MakeTime(HOUR_FROM_TIME(t), MIN_FROM_TIME(t), sec, ms); 543 var time = MakeTime(LOCAL_HOUR(this), LOCAL_MIN(this), sec, ms);
810 return %_SetValueOf(this, TimeClip(UTC(MakeDate(DAY(t), time)))); 544 return SET_LOCAL_DATE_VALUE(this, MakeDate(LOCAL_DAYS(this), time));
811 } 545 }
812 546
813 547
814 // ECMA 262 - 15.9.5.31 548 // ECMA 262 - 15.9.5.31
815 function DateSetUTCSeconds(sec, ms) { 549 function DateSetUTCSeconds(sec, ms) {
816 var t = DATE_VALUE(this); 550 CHECK_DATE(this);
551 var t = UTC_DATE_VALUE(this);
817 sec = ToNumber(sec); 552 sec = ToNumber(sec);
818 ms = %_ArgumentsLength() < 2 ? NAN_OR_MS_FROM_TIME(t) : ToNumber(ms); 553 ms = %_ArgumentsLength() < 2 ? UTC_MS(this) : ToNumber(ms);
819 var time = MakeTime(HOUR_FROM_TIME(t), MIN_FROM_TIME(t), sec, ms); 554 var time = MakeTime(UTC_HOUR(this), UTC_MIN(this), sec, ms);
820 return %_SetValueOf(this, TimeClip(MakeDate(DAY(t), time))); 555 return SET_UTC_DATE_VALUE(this, MakeDate(UTC_DAYS(this), time));
821 } 556 }
822 557
823 558
824 // ECMA 262 - 15.9.5.33 559 // ECMA 262 - 15.9.5.33
825 function DateSetMinutes(min, sec, ms) { 560 function DateSetMinutes(min, sec, ms) {
826 var t = LocalTime(DATE_VALUE(this)); 561 CHECK_DATE(this);
562 var t = LOCAL_DATE_VALUE(this);
827 min = ToNumber(min); 563 min = ToNumber(min);
828 var argc = %_ArgumentsLength(); 564 var argc = %_ArgumentsLength();
829 sec = argc < 2 ? NAN_OR_SEC_FROM_TIME(t) : ToNumber(sec); 565 sec = argc < 2 ? LOCAL_SEC(this) : ToNumber(sec);
830 ms = argc < 3 ? NAN_OR_MS_FROM_TIME(t) : ToNumber(ms); 566 ms = argc < 3 ? LOCAL_MS(this) : ToNumber(ms);
831 var time = MakeTime(HOUR_FROM_TIME(t), min, sec, ms); 567 var time = MakeTime(LOCAL_HOUR(this), min, sec, ms);
832 return %_SetValueOf(this, TimeClip(UTC(MakeDate(DAY(t), time)))); 568 return SET_LOCAL_DATE_VALUE(this, MakeDate(LOCAL_DAYS(this), time));
833 } 569 }
834 570
835 571
836 // ECMA 262 - 15.9.5.34 572 // ECMA 262 - 15.9.5.34
837 function DateSetUTCMinutes(min, sec, ms) { 573 function DateSetUTCMinutes(min, sec, ms) {
838 var t = DATE_VALUE(this); 574 CHECK_DATE(this);
575 var t = UTC_DATE_VALUE(this);
839 min = ToNumber(min); 576 min = ToNumber(min);
840 var argc = %_ArgumentsLength(); 577 var argc = %_ArgumentsLength();
841 sec = argc < 2 ? NAN_OR_SEC_FROM_TIME(t) : ToNumber(sec); 578 sec = argc < 2 ? UTC_SEC(this) : ToNumber(sec);
842 ms = argc < 3 ? NAN_OR_MS_FROM_TIME(t) : ToNumber(ms); 579 ms = argc < 3 ? UTC_MS(this) : ToNumber(ms);
843 var time = MakeTime(HOUR_FROM_TIME(t), min, sec, ms); 580 var time = MakeTime(UTC_HOUR(this), min, sec, ms);
844 return %_SetValueOf(this, TimeClip(MakeDate(DAY(t), time))); 581 return SET_UTC_DATE_VALUE(this, MakeDate(UTC_DAYS(this), time));
845 } 582 }
846 583
847 584
848 // ECMA 262 - 15.9.5.35 585 // ECMA 262 - 15.9.5.35
849 function DateSetHours(hour, min, sec, ms) { 586 function DateSetHours(hour, min, sec, ms) {
850 var t = LocalTime(DATE_VALUE(this)); 587 CHECK_DATE(this);
588 var t = LOCAL_DATE_VALUE(this);
851 hour = ToNumber(hour); 589 hour = ToNumber(hour);
852 var argc = %_ArgumentsLength(); 590 var argc = %_ArgumentsLength();
853 min = argc < 2 ? NAN_OR_MIN_FROM_TIME(t) : ToNumber(min); 591 min = argc < 2 ? LOCAL_MIN(this) : ToNumber(min);
854 sec = argc < 3 ? NAN_OR_SEC_FROM_TIME(t) : ToNumber(sec); 592 sec = argc < 3 ? LOCAL_SEC(this) : ToNumber(sec);
855 ms = argc < 4 ? NAN_OR_MS_FROM_TIME(t) : ToNumber(ms); 593 ms = argc < 4 ? LOCAL_MS(this) : ToNumber(ms);
856 var time = MakeTime(hour, min, sec, ms); 594 var time = MakeTime(hour, min, sec, ms);
857 return %_SetValueOf(this, TimeClip(UTC(MakeDate(DAY(t), time)))); 595 return SET_LOCAL_DATE_VALUE(this, MakeDate(LOCAL_DAYS(this), time));
858 } 596 }
859 597
860 598
861 // ECMA 262 - 15.9.5.34 599 // ECMA 262 - 15.9.5.34
862 function DateSetUTCHours(hour, min, sec, ms) { 600 function DateSetUTCHours(hour, min, sec, ms) {
863 var t = DATE_VALUE(this); 601 CHECK_DATE(this);
602 var t = UTC_DATE_VALUE(this);
864 hour = ToNumber(hour); 603 hour = ToNumber(hour);
865 var argc = %_ArgumentsLength(); 604 var argc = %_ArgumentsLength();
866 min = argc < 2 ? NAN_OR_MIN_FROM_TIME(t) : ToNumber(min); 605 min = argc < 2 ? UTC_MIN(this) : ToNumber(min);
867 sec = argc < 3 ? NAN_OR_SEC_FROM_TIME(t) : ToNumber(sec); 606 sec = argc < 3 ? UTC_SEC(this) : ToNumber(sec);
868 ms = argc < 4 ? NAN_OR_MS_FROM_TIME(t) : ToNumber(ms); 607 ms = argc < 4 ? UTC_MS(this) : ToNumber(ms);
869 var time = MakeTime(hour, min, sec, ms); 608 var time = MakeTime(hour, min, sec, ms);
870 return %_SetValueOf(this, TimeClip(MakeDate(DAY(t), time))); 609 return SET_UTC_DATE_VALUE(this, MakeDate(UTC_DAYS(this), time));
871 } 610 }
872 611
873 612
874 // ECMA 262 - 15.9.5.36 613 // ECMA 262 - 15.9.5.36
875 function DateSetDate(date) { 614 function DateSetDate(date) {
876 var t = LocalTime(DATE_VALUE(this)); 615 CHECK_DATE(this);
616 var t = LOCAL_DATE_VALUE(this);
877 date = ToNumber(date); 617 date = ToNumber(date);
878 var day = MakeDay(YearFromTime(t), MonthFromTime(t), date); 618 var day = MakeDay(LOCAL_YEAR(this), LOCAL_MONTH(this), date);
879 return %_SetValueOf(this, TimeClip(UTC(MakeDate(day, TimeWithinDay(t))))); 619 return SET_LOCAL_DATE_VALUE(this, MakeDate(day, LOCAL_TIME_IN_DAY(this)));
880 } 620 }
881 621
882 622
883 // ECMA 262 - 15.9.5.37 623 // ECMA 262 - 15.9.5.37
884 function DateSetUTCDate(date) { 624 function DateSetUTCDate(date) {
885 var t = DATE_VALUE(this); 625 CHECK_DATE(this);
626 var t = UTC_DATE_VALUE(this);
886 date = ToNumber(date); 627 date = ToNumber(date);
887 var day = MakeDay(YearFromTime(t), MonthFromTime(t), date); 628 var day = MakeDay(UTC_YEAR(this), UTC_MONTH(this), date);
888 return %_SetValueOf(this, TimeClip(MakeDate(day, TimeWithinDay(t)))); 629 return SET_UTC_DATE_VALUE(this, MakeDate(day, UTC_TIME_IN_DAY(this)));
889 } 630 }
890 631
891 632
892 // ECMA 262 - 15.9.5.38 633 // ECMA 262 - 15.9.5.38
893 function DateSetMonth(month, date) { 634 function DateSetMonth(month, date) {
894 var t = LocalTime(DATE_VALUE(this)); 635 CHECK_DATE(this);
636 var t = LOCAL_DATE_VALUE(this);
895 month = ToNumber(month); 637 month = ToNumber(month);
896 date = %_ArgumentsLength() < 2 ? NAN_OR_DATE_FROM_TIME(t) : ToNumber(date); 638 date = %_ArgumentsLength() < 2 ? LOCAL_DAY(this) : ToNumber(date);
897 var day = MakeDay(YearFromTime(t), month, date); 639 var day = MakeDay(LOCAL_YEAR(this), month, date);
898 return %_SetValueOf(this, TimeClip(UTC(MakeDate(day, TimeWithinDay(t))))); 640 return SET_LOCAL_DATE_VALUE(this, MakeDate(day, LOCAL_TIME_IN_DAY(this)));
899 } 641 }
900 642
901 643
902 // ECMA 262 - 15.9.5.39 644 // ECMA 262 - 15.9.5.39
903 function DateSetUTCMonth(month, date) { 645 function DateSetUTCMonth(month, date) {
904 var t = DATE_VALUE(this); 646 CHECK_DATE(this);
647 var t = UTC_DATE_VALUE(this);
905 month = ToNumber(month); 648 month = ToNumber(month);
906 date = %_ArgumentsLength() < 2 ? NAN_OR_DATE_FROM_TIME(t) : ToNumber(date); 649 date = %_ArgumentsLength() < 2 ? UTC_DAY(this) : ToNumber(date);
907 var day = MakeDay(YearFromTime(t), month, date); 650 var day = MakeDay(UTC_YEAR(this), month, date);
908 return %_SetValueOf(this, TimeClip(MakeDate(day, TimeWithinDay(t)))); 651 return SET_UTC_DATE_VALUE(this, MakeDate(day, UTC_TIME_IN_DAY(this)));
909 } 652 }
910 653
911 654
912 // ECMA 262 - 15.9.5.40 655 // ECMA 262 - 15.9.5.40
913 function DateSetFullYear(year, month, date) { 656 function DateSetFullYear(year, month, date) {
914 var t = DATE_VALUE(this); 657 CHECK_DATE(this);
915 t = NUMBER_IS_NAN(t) ? 0 : LocalTimeNoCheck(t); 658 var t = LOCAL_DATE_VALUE(this);
916 year = ToNumber(year); 659 year = ToNumber(year);
917 var argc = %_ArgumentsLength(); 660 var argc = %_ArgumentsLength();
918 month = argc < 2 ? MonthFromTime(t) : ToNumber(month); 661 var time ;
919 date = argc < 3 ? DateFromTime(t) : ToNumber(date); 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 }
920 var day = MakeDay(year, month, date); 671 var day = MakeDay(year, month, date);
921 return %_SetValueOf(this, TimeClip(UTC(MakeDate(day, TimeWithinDay(t))))); 672 return SET_LOCAL_DATE_VALUE(this, MakeDate(day, time));
922 } 673 }
923 674
924 675
925 // ECMA 262 - 15.9.5.41 676 // ECMA 262 - 15.9.5.41
926 function DateSetUTCFullYear(year, month, date) { 677 function DateSetUTCFullYear(year, month, date) {
927 var t = DATE_VALUE(this); 678 CHECK_DATE(this);
928 if (NUMBER_IS_NAN(t)) t = 0; 679 var t = UTC_DATE_VALUE(this);
929 var argc = %_ArgumentsLength();
930 year = ToNumber(year); 680 year = ToNumber(year);
931 month = argc < 2 ? MonthFromTime(t) : ToNumber(month); 681 var argc = %_ArgumentsLength();
932 date = argc < 3 ? DateFromTime(t) : ToNumber(date); 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 }
933 var day = MakeDay(year, month, date); 692 var day = MakeDay(year, month, date);
934 return %_SetValueOf(this, TimeClip(MakeDate(day, TimeWithinDay(t)))); 693 return SET_UTC_DATE_VALUE(this, MakeDate(day, time));
935 } 694 }
936 695
937 696
938 // ECMA 262 - 15.9.5.42 697 // ECMA 262 - 15.9.5.42
939 function DateToUTCString() { 698 function DateToUTCString() {
940 var t = DATE_VALUE(this); 699 CHECK_DATE(this);
700 var t = UTC_DATE_VALUE(this);
941 if (NUMBER_IS_NAN(t)) return kInvalidDate; 701 if (NUMBER_IS_NAN(t)) return kInvalidDate;
942 // Return UTC string of the form: Sat, 31 Jan 1970 23:00:00 GMT 702 // Return UTC string of the form: Sat, 31 Jan 1970 23:00:00 GMT
943 return WeekDays[WeekDay(t)] + ', ' 703 return WeekDays[UTC_WEEKDAY(this)] + ', '
944 + TwoDigitString(DateFromTime(t)) + ' ' 704 + TwoDigitString(UTC_DAY(this)) + ' '
945 + Months[MonthFromTime(t)] + ' ' 705 + Months[UTC_MONTH(this)] + ' '
946 + YearFromTime(t) + ' ' 706 + UTC_YEAR(this) + ' '
947 + TimeString(t) + ' GMT'; 707 + TimeStringUTC(this) + ' GMT';
948 } 708 }
949 709
950 710
951 // ECMA 262 - B.2.4 711 // ECMA 262 - B.2.4
952 function DateGetYear() { 712 function DateGetYear() {
953 var t = DATE_VALUE(this); 713 CHECK_DATE(this);
954 if (NUMBER_IS_NAN(t)) return $NaN; 714 return LOCAL_YEAR(this) - 1900;
955 return YearFromTime(LocalTimeNoCheck(t)) - 1900;
956 } 715 }
957 716
958 717
959 // ECMA 262 - B.2.5 718 // ECMA 262 - B.2.5
960 function DateSetYear(year) { 719 function DateSetYear(year) {
961 var t = LocalTime(DATE_VALUE(this)); 720 CHECK_DATE(this);
962 if (NUMBER_IS_NAN(t)) t = 0;
963 year = ToNumber(year); 721 year = ToNumber(year);
964 if (NUMBER_IS_NAN(year)) return %_SetValueOf(this, $NaN); 722 if (NUMBER_IS_NAN(year)) return SET_UTC_DATE_VALUE(this, $NaN);
965 year = (0 <= TO_INTEGER(year) && TO_INTEGER(year) <= 99) 723 year = (0 <= TO_INTEGER(year) && TO_INTEGER(year) <= 99)
966 ? 1900 + TO_INTEGER(year) : year; 724 ? 1900 + TO_INTEGER(year) : year;
967 var day = MakeDay(year, MonthFromTime(t), DateFromTime(t)); 725 var t = LOCAL_DATE_VALUE(this);
968 return %_SetValueOf(this, TimeClip(UTC(MakeDate(day, TimeWithinDay(t))))); 726 var month, date, time;
969 } 727 if (NUMBER_IS_NAN(t)) {
970 728 month = 0;
971 729 date = 1;
730 time = 0;
731 } else {
732 month = LOCAL_MONTH(this);
733 date = LOCAL_DAY(this);
734 time = TimeWithinDay(t);
735 }
736 var day = MakeDay(year, month, date);
737 return SET_LOCAL_DATE_VALUE(this, MakeDate(day, time));
738 }
739
740
972 // ECMA 262 - B.2.6 741 // ECMA 262 - B.2.6
973 // 742 //
974 // Notice that this does not follow ECMA 262 completely. ECMA 262 743 // Notice that this does not follow ECMA 262 completely. ECMA 262
975 // says that toGMTString should be the same Function object as 744 // says that toGMTString should be the same Function object as
976 // toUTCString. JSC does not do this, so for compatibility we do not 745 // toUTCString. JSC does not do this, so for compatibility we do not
977 // do that either. Instead, we create a new function whose name 746 // do that either. Instead, we create a new function whose name
978 // property will return toGMTString. 747 // property will return toGMTString.
979 function DateToGMTString() { 748 function DateToGMTString() {
980 return %_CallFunction(this, DateToUTCString); 749 return %_CallFunction(this, DateToUTCString);
981 } 750 }
982 751
983 752
984 function PadInt(n, digits) { 753 function PadInt(n, digits) {
985 if (digits == 1) return n; 754 if (digits == 1) return n;
986 return n < MathPow(10, digits - 1) ? '0' + PadInt(n, digits - 1) : n; 755 return n < MathPow(10, digits - 1) ? '0' + PadInt(n, digits - 1) : n;
987 } 756 }
988 757
989 758
990 // ECMA 262 - 15.9.5.43 759 // ECMA 262 - 15.9.5.43
991 function DateToISOString() { 760 function DateToISOString() {
992 var t = DATE_VALUE(this); 761 CHECK_DATE(this);
762 var t = UTC_DATE_VALUE(this);
993 if (NUMBER_IS_NAN(t)) throw MakeRangeError("invalid_time_value", []); 763 if (NUMBER_IS_NAN(t)) throw MakeRangeError("invalid_time_value", []);
994 var year = this.getUTCFullYear(); 764 var year = this.getUTCFullYear();
995 var year_string; 765 var year_string;
996 if (year >= 0 && year <= 9999) { 766 if (year >= 0 && year <= 9999) {
997 year_string = PadInt(year, 4); 767 year_string = PadInt(year, 4);
998 } else { 768 } else {
999 if (year < 0) { 769 if (year < 0) {
1000 year_string = "-" + PadInt(-year, 6); 770 year_string = "-" + PadInt(-year, 6);
1001 } else { 771 } else {
1002 year_string = "+" + PadInt(year, 6); 772 year_string = "+" + PadInt(year, 6);
(...skipping 14 matching lines...) Expand all
1017 var o = ToObject(this); 787 var o = ToObject(this);
1018 var tv = DefaultNumber(o); 788 var tv = DefaultNumber(o);
1019 if (IS_NUMBER(tv) && !NUMBER_IS_FINITE(tv)) { 789 if (IS_NUMBER(tv) && !NUMBER_IS_FINITE(tv)) {
1020 return null; 790 return null;
1021 } 791 }
1022 return o.toISOString(); 792 return o.toISOString();
1023 } 793 }
1024 794
1025 795
1026 function ResetDateCache() { 796 function ResetDateCache() {
1027
1028 // Reset the local_time_offset:
1029 local_time_offset = %DateLocalTimeOffset();
1030
1031 // Reset the DST offset cache:
1032 var cache = DST_offset_cache;
1033 cache.offset = 0;
1034 cache.start = 0;
1035 cache.end = -1;
1036 cache.increment = 0;
1037 cache.initial_increment = 19 * msPerDay;
1038
1039 // Reset the timezone cache: 797 // Reset the timezone cache:
1040 timezone_cache_time = $NaN; 798 timezone_cache_time = $NaN;
1041 timezone_cache_timezone = undefined; 799 timezone_cache_timezone = undefined;
1042 800
1043 // Reset the ltcache:
1044 ltcache.key = null;
1045 ltcache.val = null;
1046
1047 // Reset the ymd_from_time_cache:
1048 ymd_from_time_cache = [$NaN, $NaN, $NaN];
1049 ymd_from_time_cached_time = $NaN;
1050
1051 // Reset the date cache: 801 // Reset the date cache:
1052 cache = Date_cache; 802 cache = Date_cache;
1053 cache.time = $NaN; 803 cache.time = $NaN;
1054 cache.year = $NaN;
1055 cache.string = null; 804 cache.string = null;
1056 } 805 }
1057 806
1058 807
1059 // ------------------------------------------------------------------- 808 // -------------------------------------------------------------------
1060 809
1061 function SetUpDate() { 810 function SetUpDate() {
1062 %CheckIsBootstrapping(); 811 %CheckIsBootstrapping();
1063 // Set up non-enumerable properties of the Date object itself. 812 // Set up non-enumerable properties of the Date object itself.
1064 InstallFunctions($Date, DONT_ENUM, $Array( 813 InstallFunctions($Date, DONT_ENUM, $Array(
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1116 "toGMTString", DateToGMTString, 865 "toGMTString", DateToGMTString,
1117 "toUTCString", DateToUTCString, 866 "toUTCString", DateToUTCString,
1118 "getYear", DateGetYear, 867 "getYear", DateGetYear,
1119 "setYear", DateSetYear, 868 "setYear", DateSetYear,
1120 "toISOString", DateToISOString, 869 "toISOString", DateToISOString,
1121 "toJSON", DateToJSON 870 "toJSON", DateToJSON
1122 )); 871 ));
1123 } 872 }
1124 873
1125 SetUpDate(); 874 SetUpDate();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698