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

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

Powered by Google App Engine
This is Rietveld 408576698