OLD | NEW |
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 Loading... |
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 Loading... |
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 LocalTimezoneString(date) { |
501 var old_timezone = timezone_cache_timezone; | 248 var timezone = LocalTimezone(UTC_DATE_VALUE(date)); |
502 var timezone = LocalTimezone(time); | |
503 if (old_timezone && timezone != old_timezone) { | |
504 // If the timezone string has changed from the one that we cached, | |
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 | 249 |
515 var timezoneOffset = | 250 var timezoneOffset = TIMEZONE_OFFSET(date); |
516 (DaylightSavingsOffset(time) + local_time_offset) / msPerMinute; | |
517 var sign = (timezoneOffset >= 0) ? 1 : -1; | 251 var sign = (timezoneOffset >= 0) ? 1 : -1; |
518 var hours = FLOOR((sign * timezoneOffset)/60); | 252 var hours = FLOOR((sign * timezoneOffset)/60); |
519 var min = FLOOR((sign * timezoneOffset)%60); | 253 var min = FLOOR((sign * timezoneOffset)%60); |
520 var gmt = ' GMT' + ((sign == 1) ? '+' : '-') + | 254 var gmt = ' GMT' + ((sign == 1) ? '+' : '-') + |
521 TwoDigitString(hours) + TwoDigitString(min); | 255 TwoDigitString(hours) + TwoDigitString(min); |
522 return gmt + ' (' + timezone + ')'; | 256 return gmt + ' (' + timezone + ')'; |
523 } | 257 } |
524 | 258 |
525 | 259 |
526 function DatePrintString(time) { | 260 function DatePrintString(date) { |
527 return DateString(time) + ' ' + TimeString(time); | 261 return DateString(date) + ' ' + TimeString(date); |
528 } | 262 } |
529 | 263 |
530 // ------------------------------------------------------------------- | 264 // ------------------------------------------------------------------- |
531 | 265 |
532 // Reused output buffer. Used when parsing date strings. | 266 // Reused output buffer. Used when parsing date strings. |
533 var parse_buffer = $Array(8); | 267 var parse_buffer = $Array(8); |
534 | 268 |
535 // ECMA 262 - 15.9.4.2 | 269 // ECMA 262 - 15.9.4.2 |
536 function DateParse(string) { | 270 function DateParse(string) { |
537 var arr = %DateParseString(ToString(string), parse_buffer); | 271 var arr = %DateParseString(ToString(string), parse_buffer); |
(...skipping 19 matching lines...) Expand all Loading... |
557 date = argc > 2 ? ToNumber(date) : 1; | 291 date = argc > 2 ? ToNumber(date) : 1; |
558 hours = argc > 3 ? ToNumber(hours) : 0; | 292 hours = argc > 3 ? ToNumber(hours) : 0; |
559 minutes = argc > 4 ? ToNumber(minutes) : 0; | 293 minutes = argc > 4 ? ToNumber(minutes) : 0; |
560 seconds = argc > 5 ? ToNumber(seconds) : 0; | 294 seconds = argc > 5 ? ToNumber(seconds) : 0; |
561 ms = argc > 6 ? ToNumber(ms) : 0; | 295 ms = argc > 6 ? ToNumber(ms) : 0; |
562 year = (!NUMBER_IS_NAN(year) && | 296 year = (!NUMBER_IS_NAN(year) && |
563 0 <= TO_INTEGER(year) && | 297 0 <= TO_INTEGER(year) && |
564 TO_INTEGER(year) <= 99) ? 1900 + TO_INTEGER(year) : year; | 298 TO_INTEGER(year) <= 99) ? 1900 + TO_INTEGER(year) : year; |
565 var day = MakeDay(year, month, date); | 299 var day = MakeDay(year, month, date); |
566 var time = MakeTime(hours, minutes, seconds, ms); | 300 var time = MakeTime(hours, minutes, seconds, ms); |
567 return %_SetValueOf(this, TimeClip(MakeDate(day, time))); | 301 return TimeClip(MakeDate(day, time)); |
568 } | 302 } |
569 | 303 |
570 | 304 |
571 // Mozilla-specific extension. Returns the number of milliseconds | 305 // Mozilla-specific extension. Returns the number of milliseconds |
572 // elapsed since 1 January 1970 00:00:00 UTC. | 306 // elapsed since 1 January 1970 00:00:00 UTC. |
573 function DateNow() { | 307 function DateNow() { |
574 return %DateCurrentTime(); | 308 return %DateCurrentTime(); |
575 } | 309 } |
576 | 310 |
577 | 311 |
578 // ECMA 262 - 15.9.5.2 | 312 // ECMA 262 - 15.9.5.2 |
579 function DateToString() { | 313 function DateToString() { |
580 var t = DATE_VALUE(this); | 314 CHECK_DATE(this); |
| 315 var t = UTC_DATE_VALUE(this) |
581 if (NUMBER_IS_NAN(t)) return kInvalidDate; | 316 if (NUMBER_IS_NAN(t)) return kInvalidDate; |
582 var time_zone_string = LocalTimezoneString(t); // May update local offset. | 317 var time_zone_string = LocalTimezoneString(this) |
583 return DatePrintString(LocalTimeNoCheck(t)) + time_zone_string; | 318 return DatePrintString(this) + time_zone_string; |
584 } | 319 } |
585 | 320 |
586 | 321 |
587 // ECMA 262 - 15.9.5.3 | 322 // ECMA 262 - 15.9.5.3 |
588 function DateToDateString() { | 323 function DateToDateString() { |
589 var t = DATE_VALUE(this); | 324 CHECK_DATE(this); |
| 325 var t = UTC_DATE_VALUE(this); |
590 if (NUMBER_IS_NAN(t)) return kInvalidDate; | 326 if (NUMBER_IS_NAN(t)) return kInvalidDate; |
591 return DateString(LocalTimeNoCheck(t)); | 327 return DateString(this); |
592 } | 328 } |
593 | 329 |
594 | 330 |
595 // ECMA 262 - 15.9.5.4 | 331 // ECMA 262 - 15.9.5.4 |
596 function DateToTimeString() { | 332 function DateToTimeString() { |
597 var t = DATE_VALUE(this); | 333 CHECK_DATE(this); |
| 334 var t = UTC_DATE_VALUE(this); |
598 if (NUMBER_IS_NAN(t)) return kInvalidDate; | 335 if (NUMBER_IS_NAN(t)) return kInvalidDate; |
599 var time_zone_string = LocalTimezoneString(t); // May update local offset. | 336 var time_zone_string = LocalTimezoneString(this); |
600 return TimeString(LocalTimeNoCheck(t)) + time_zone_string; | 337 return TimeString(this) + time_zone_string; |
601 } | 338 } |
602 | 339 |
603 | 340 |
604 // ECMA 262 - 15.9.5.5 | 341 // ECMA 262 - 15.9.5.5 |
605 function DateToLocaleString() { | 342 function DateToLocaleString() { |
606 return %_CallFunction(this, DateToString); | 343 return %_CallFunction(this, DateToString); |
607 } | 344 } |
608 | 345 |
609 | 346 |
610 // ECMA 262 - 15.9.5.6 | 347 // ECMA 262 - 15.9.5.6 |
611 function DateToLocaleDateString() { | 348 function DateToLocaleDateString() { |
612 var t = DATE_VALUE(this); | 349 CHECK_DATE(this); |
| 350 var t = UTC_DATE_VALUE(this); |
613 if (NUMBER_IS_NAN(t)) return kInvalidDate; | 351 if (NUMBER_IS_NAN(t)) return kInvalidDate; |
614 return LongDateString(LocalTimeNoCheck(t)); | 352 return LongDateString(this); |
615 } | 353 } |
616 | 354 |
617 | 355 |
618 // ECMA 262 - 15.9.5.7 | 356 // ECMA 262 - 15.9.5.7 |
619 function DateToLocaleTimeString() { | 357 function DateToLocaleTimeString() { |
620 var t = DATE_VALUE(this); | 358 CHECK_DATE(this); |
| 359 var t = UTC_DATE_VALUE(this); |
621 if (NUMBER_IS_NAN(t)) return kInvalidDate; | 360 if (NUMBER_IS_NAN(t)) return kInvalidDate; |
622 var lt = LocalTimeNoCheck(t); | 361 return TimeString(this); |
623 return TimeString(lt); | |
624 } | 362 } |
625 | 363 |
626 | 364 |
627 // ECMA 262 - 15.9.5.8 | 365 // ECMA 262 - 15.9.5.8 |
628 function DateValueOf() { | 366 function DateValueOf() { |
629 return DATE_VALUE(this); | 367 CHECK_DATE(this); |
| 368 return UTC_DATE_VALUE(this); |
630 } | 369 } |
631 | 370 |
632 | 371 |
633 // ECMA 262 - 15.9.5.9 | 372 // ECMA 262 - 15.9.5.9 |
634 function DateGetTime() { | 373 function DateGetTime() { |
635 return DATE_VALUE(this); | 374 CHECK_DATE(this); |
| 375 return UTC_DATE_VALUE(this); |
636 } | 376 } |
637 | 377 |
638 | 378 |
639 // ECMA 262 - 15.9.5.10 | 379 // ECMA 262 - 15.9.5.10 |
640 function DateGetFullYear() { | 380 function DateGetFullYear() { |
641 var t = DATE_VALUE(this); | 381 CHECK_DATE(this); |
642 if (NUMBER_IS_NAN(t)) return t; | 382 return LOCAL_YEAR(this); |
643 var cache = Date_cache; | |
644 if (cache.time === t) return cache.year; | |
645 return YearFromTime(LocalTimeNoCheck(t)); | |
646 } | 383 } |
647 | 384 |
648 | 385 |
649 // ECMA 262 - 15.9.5.11 | 386 // ECMA 262 - 15.9.5.11 |
650 function DateGetUTCFullYear() { | 387 function DateGetUTCFullYear() { |
651 var t = DATE_VALUE(this); | 388 CHECK_DATE(this); |
652 if (NUMBER_IS_NAN(t)) return t; | 389 return UTC_YEAR(this); |
653 return YearFromTime(t); | |
654 } | 390 } |
655 | 391 |
656 | 392 |
657 // ECMA 262 - 15.9.5.12 | 393 // ECMA 262 - 15.9.5.12 |
658 function DateGetMonth() { | 394 function DateGetMonth() { |
659 var t = DATE_VALUE(this); | 395 CHECK_DATE(this); |
660 if (NUMBER_IS_NAN(t)) return t; | 396 return LOCAL_MONTH(this); |
661 return MonthFromTime(LocalTimeNoCheck(t)); | |
662 } | 397 } |
663 | 398 |
664 | 399 |
665 // ECMA 262 - 15.9.5.13 | 400 // ECMA 262 - 15.9.5.13 |
666 function DateGetUTCMonth() { | 401 function DateGetUTCMonth() { |
667 var t = DATE_VALUE(this); | 402 CHECK_DATE(this); |
668 if (NUMBER_IS_NAN(t)) return t; | 403 return UTC_MONTH(this); |
669 return MonthFromTime(t); | |
670 } | 404 } |
671 | 405 |
672 | 406 |
673 // ECMA 262 - 15.9.5.14 | 407 // ECMA 262 - 15.9.5.14 |
674 function DateGetDate() { | 408 function DateGetDate() { |
675 var t = DATE_VALUE(this); | 409 CHECK_DATE(this); |
676 if (NUMBER_IS_NAN(t)) return t; | 410 return LOCAL_DAY(this); |
677 return DateFromTime(LocalTimeNoCheck(t)); | |
678 } | 411 } |
679 | 412 |
680 | 413 |
681 // ECMA 262 - 15.9.5.15 | 414 // ECMA 262 - 15.9.5.15 |
682 function DateGetUTCDate() { | 415 function DateGetUTCDate() { |
683 var t = DATE_VALUE(this); | 416 CHECK_DATE(this); |
684 return NAN_OR_DATE_FROM_TIME(t); | 417 return UTC_DAY(this); |
685 } | 418 } |
686 | 419 |
687 | 420 |
688 // ECMA 262 - 15.9.5.16 | 421 // ECMA 262 - 15.9.5.16 |
689 function DateGetDay() { | 422 function DateGetDay() { |
690 var t = DATE_VALUE(this); | 423 CHECK_DATE(this); |
691 if (NUMBER_IS_NAN(t)) return t; | 424 return LOCAL_WEEKDAY(this); |
692 return WeekDay(LocalTimeNoCheck(t)); | |
693 } | 425 } |
694 | 426 |
695 | 427 |
696 // ECMA 262 - 15.9.5.17 | 428 // ECMA 262 - 15.9.5.17 |
697 function DateGetUTCDay() { | 429 function DateGetUTCDay() { |
698 var t = DATE_VALUE(this); | 430 CHECK_DATE(this); |
699 if (NUMBER_IS_NAN(t)) return t; | 431 return UTC_WEEKDAY(this); |
700 return WeekDay(t); | |
701 } | 432 } |
702 | 433 |
703 | 434 |
704 // ECMA 262 - 15.9.5.18 | 435 // ECMA 262 - 15.9.5.18 |
705 function DateGetHours() { | 436 function DateGetHours() { |
706 var t = DATE_VALUE(this); | 437 CHECK_DATE(this); |
707 if (NUMBER_IS_NAN(t)) return t; | 438 return LOCAL_HOUR(this); |
708 return HOUR_FROM_TIME(LocalTimeNoCheck(t)); | |
709 } | 439 } |
710 | 440 |
711 | 441 |
712 // ECMA 262 - 15.9.5.19 | 442 // ECMA 262 - 15.9.5.19 |
713 function DateGetUTCHours() { | 443 function DateGetUTCHours() { |
714 var t = DATE_VALUE(this); | 444 CHECK_DATE(this); |
715 if (NUMBER_IS_NAN(t)) return t; | 445 return UTC_HOUR(this); |
716 return HOUR_FROM_TIME(t); | |
717 } | 446 } |
718 | 447 |
719 | 448 |
720 // ECMA 262 - 15.9.5.20 | 449 // ECMA 262 - 15.9.5.20 |
721 function DateGetMinutes() { | 450 function DateGetMinutes() { |
722 var t = DATE_VALUE(this); | 451 CHECK_DATE(this); |
723 if (NUMBER_IS_NAN(t)) return t; | 452 return LOCAL_MIN(this); |
724 return MIN_FROM_TIME(LocalTimeNoCheck(t)); | |
725 } | 453 } |
726 | 454 |
727 | 455 |
728 // ECMA 262 - 15.9.5.21 | 456 // ECMA 262 - 15.9.5.21 |
729 function DateGetUTCMinutes() { | 457 function DateGetUTCMinutes() { |
730 var t = DATE_VALUE(this); | 458 CHECK_DATE(this); |
731 return NAN_OR_MIN_FROM_TIME(t); | 459 return UTC_MIN(this); |
732 } | 460 } |
733 | 461 |
734 | 462 |
735 // ECMA 262 - 15.9.5.22 | 463 // ECMA 262 - 15.9.5.22 |
736 function DateGetSeconds() { | 464 function DateGetSeconds() { |
737 var t = DATE_VALUE(this); | 465 CHECK_DATE(this); |
738 if (NUMBER_IS_NAN(t)) return t; | 466 return LOCAL_SEC(this); |
739 return SEC_FROM_TIME(LocalTimeNoCheck(t)); | |
740 } | 467 } |
741 | 468 |
742 | 469 |
743 // ECMA 262 - 15.9.5.23 | 470 // ECMA 262 - 15.9.5.23 |
744 function DateGetUTCSeconds() { | 471 function DateGetUTCSeconds() { |
745 var t = DATE_VALUE(this); | 472 CHECK_DATE(this); |
746 return NAN_OR_SEC_FROM_TIME(t); | 473 return UTC_SEC(this) |
747 } | 474 } |
748 | 475 |
749 | 476 |
750 // ECMA 262 - 15.9.5.24 | 477 // ECMA 262 - 15.9.5.24 |
751 function DateGetMilliseconds() { | 478 function DateGetMilliseconds() { |
752 var t = DATE_VALUE(this); | 479 CHECK_DATE(this); |
753 if (NUMBER_IS_NAN(t)) return t; | 480 return LOCAL_MS(this); |
754 return MS_FROM_TIME(LocalTimeNoCheck(t)); | |
755 } | 481 } |
756 | 482 |
757 | 483 |
758 // ECMA 262 - 15.9.5.25 | 484 // ECMA 262 - 15.9.5.25 |
759 function DateGetUTCMilliseconds() { | 485 function DateGetUTCMilliseconds() { |
760 var t = DATE_VALUE(this); | 486 CHECK_DATE(this); |
761 return NAN_OR_MS_FROM_TIME(t); | 487 return UTC_MS(this); |
762 } | 488 } |
763 | 489 |
764 | 490 |
765 // ECMA 262 - 15.9.5.26 | 491 // ECMA 262 - 15.9.5.26 |
766 function DateGetTimezoneOffset() { | 492 function DateGetTimezoneOffset() { |
767 var t = DATE_VALUE(this); | 493 CHECK_DATE(this); |
768 if (NUMBER_IS_NAN(t)) return t; | 494 return TIMEZONE_OFFSET(this); |
769 return (t - LocalTimeNoCheck(t)) / msPerMinute; | |
770 } | 495 } |
771 | 496 |
772 | 497 |
773 // ECMA 262 - 15.9.5.27 | 498 // ECMA 262 - 15.9.5.27 |
774 function DateSetTime(ms) { | 499 function DateSetTime(ms) { |
775 if (!IS_DATE(this)) ThrowDateTypeError(); | 500 CHECK_DATE(this); |
776 return %_SetValueOf(this, TimeClip(ToNumber(ms))); | 501 return SET_UTC_DATE_VALUE(this, ToNumber(ms)); |
777 } | 502 } |
778 | 503 |
779 | 504 |
780 // ECMA 262 - 15.9.5.28 | 505 // ECMA 262 - 15.9.5.28 |
781 function DateSetMilliseconds(ms) { | 506 function DateSetMilliseconds(ms) { |
782 var t = LocalTime(DATE_VALUE(this)); | 507 CHECK_DATE(this); |
| 508 var t = LOCAL_DATE_VALUE(this); |
783 ms = ToNumber(ms); | 509 ms = ToNumber(ms); |
784 var time = MakeTime(HOUR_FROM_TIME(t), | 510 var time = MakeTime(LOCAL_HOUR(this), LOCAL_MIN(this), LOCAL_SEC(this), ms); |
785 MIN_FROM_TIME(t), | 511 SET_LOCAL_DATE_VALUE(this, MakeDate(LOCAL_DAYS(this), time)); |
786 SEC_FROM_TIME(t), | 512 return this; |
787 ms); | |
788 return %_SetValueOf(this, TimeClip(UTC(MakeDate(DAY(t), time)))); | |
789 } | 513 } |
790 | 514 |
791 | 515 |
792 // ECMA 262 - 15.9.5.29 | 516 // ECMA 262 - 15.9.5.29 |
793 function DateSetUTCMilliseconds(ms) { | 517 function DateSetUTCMilliseconds(ms) { |
794 var t = DATE_VALUE(this); | 518 CHECK_DATE(this); |
| 519 var t = UTC_DATE_VALUE(this); |
795 ms = ToNumber(ms); | 520 ms = ToNumber(ms); |
796 var time = MakeTime(HOUR_FROM_TIME(t), | 521 var time = MakeTime(UTC_HOUR(this), |
797 MIN_FROM_TIME(t), | 522 UTC_MIN(this), |
798 SEC_FROM_TIME(t), | 523 UTC_SEC(this), |
799 ms); | 524 ms); |
800 return %_SetValueOf(this, TimeClip(MakeDate(DAY(t), time))); | 525 return SET_UTC_DATE_VALUE(this, MakeDate(UTC_DAYS(this), time)); |
801 } | 526 } |
802 | 527 |
803 | 528 |
804 // ECMA 262 - 15.9.5.30 | 529 // ECMA 262 - 15.9.5.30 |
805 function DateSetSeconds(sec, ms) { | 530 function DateSetSeconds(sec, ms) { |
806 var t = LocalTime(DATE_VALUE(this)); | 531 CHECK_DATE(this); |
| 532 var t = LOCAL_DATE_VALUE(this); |
807 sec = ToNumber(sec); | 533 sec = ToNumber(sec); |
808 ms = %_ArgumentsLength() < 2 ? NAN_OR_MS_FROM_TIME(t) : ToNumber(ms); | 534 ms = %_ArgumentsLength() < 2 ? LOCAL_MS(this) : ToNumber(ms); |
809 var time = MakeTime(HOUR_FROM_TIME(t), MIN_FROM_TIME(t), sec, ms); | 535 var time = MakeTime(LOCAL_HOUR(this), LOCAL_MIN(this), sec, ms); |
810 return %_SetValueOf(this, TimeClip(UTC(MakeDate(DAY(t), time)))); | 536 return SET_LOCAL_DATE_VALUE(this, MakeDate(LOCAL_DAYS(this), time)); |
811 } | 537 } |
812 | 538 |
813 | 539 |
814 // ECMA 262 - 15.9.5.31 | 540 // ECMA 262 - 15.9.5.31 |
815 function DateSetUTCSeconds(sec, ms) { | 541 function DateSetUTCSeconds(sec, ms) { |
816 var t = DATE_VALUE(this); | 542 CHECK_DATE(this); |
| 543 var t = UTC_DATE_VALUE(this); |
817 sec = ToNumber(sec); | 544 sec = ToNumber(sec); |
818 ms = %_ArgumentsLength() < 2 ? NAN_OR_MS_FROM_TIME(t) : ToNumber(ms); | 545 ms = %_ArgumentsLength() < 2 ? UTC_MS(this) : ToNumber(ms); |
819 var time = MakeTime(HOUR_FROM_TIME(t), MIN_FROM_TIME(t), sec, ms); | 546 var time = MakeTime(UTC_HOUR(this), UTC_MIN(this), sec, ms); |
820 return %_SetValueOf(this, TimeClip(MakeDate(DAY(t), time))); | 547 return SET_UTC_DATE_VALUE(this, MakeDate(UTC_DAYS(this), time)); |
821 } | 548 } |
822 | 549 |
823 | 550 |
824 // ECMA 262 - 15.9.5.33 | 551 // ECMA 262 - 15.9.5.33 |
825 function DateSetMinutes(min, sec, ms) { | 552 function DateSetMinutes(min, sec, ms) { |
826 var t = LocalTime(DATE_VALUE(this)); | 553 CHECK_DATE(this); |
| 554 var t = LOCAL_DATE_VALUE(this); |
827 min = ToNumber(min); | 555 min = ToNumber(min); |
828 var argc = %_ArgumentsLength(); | 556 var argc = %_ArgumentsLength(); |
829 sec = argc < 2 ? NAN_OR_SEC_FROM_TIME(t) : ToNumber(sec); | 557 sec = argc < 2 ? LOCAL_SEC(this) : ToNumber(sec); |
830 ms = argc < 3 ? NAN_OR_MS_FROM_TIME(t) : ToNumber(ms); | 558 ms = argc < 3 ? LOCAL_MS(this) : ToNumber(ms); |
831 var time = MakeTime(HOUR_FROM_TIME(t), min, sec, ms); | 559 var time = MakeTime(LOCAL_HOUR(this), min, sec, ms); |
832 return %_SetValueOf(this, TimeClip(UTC(MakeDate(DAY(t), time)))); | 560 return SET_LOCAL_DATE_VALUE(this, MakeDate(LOCAL_DAYS(this), time)); |
833 } | 561 } |
834 | 562 |
835 | 563 |
836 // ECMA 262 - 15.9.5.34 | 564 // ECMA 262 - 15.9.5.34 |
837 function DateSetUTCMinutes(min, sec, ms) { | 565 function DateSetUTCMinutes(min, sec, ms) { |
838 var t = DATE_VALUE(this); | 566 CHECK_DATE(this); |
| 567 var t = UTC_DATE_VALUE(this); |
839 min = ToNumber(min); | 568 min = ToNumber(min); |
840 var argc = %_ArgumentsLength(); | 569 var argc = %_ArgumentsLength(); |
841 sec = argc < 2 ? NAN_OR_SEC_FROM_TIME(t) : ToNumber(sec); | 570 sec = argc < 2 ? UTC_SEC(this) : ToNumber(sec); |
842 ms = argc < 3 ? NAN_OR_MS_FROM_TIME(t) : ToNumber(ms); | 571 ms = argc < 3 ? UTC_MS(this) : ToNumber(ms); |
843 var time = MakeTime(HOUR_FROM_TIME(t), min, sec, ms); | 572 var time = MakeTime(UTC_HOUR(this), min, sec, ms); |
844 return %_SetValueOf(this, TimeClip(MakeDate(DAY(t), time))); | 573 return SET_UTC_DATE_VALUE(this, MakeDate(UTC_DAYS(this), time)); |
845 } | 574 } |
846 | 575 |
847 | 576 |
848 // ECMA 262 - 15.9.5.35 | 577 // ECMA 262 - 15.9.5.35 |
849 function DateSetHours(hour, min, sec, ms) { | 578 function DateSetHours(hour, min, sec, ms) { |
850 var t = LocalTime(DATE_VALUE(this)); | 579 CHECK_DATE(this); |
| 580 var t = LOCAL_DATE_VALUE(this); |
851 hour = ToNumber(hour); | 581 hour = ToNumber(hour); |
852 var argc = %_ArgumentsLength(); | 582 var argc = %_ArgumentsLength(); |
853 min = argc < 2 ? NAN_OR_MIN_FROM_TIME(t) : ToNumber(min); | 583 min = argc < 2 ? LOCAL_MIN(this) : ToNumber(min); |
854 sec = argc < 3 ? NAN_OR_SEC_FROM_TIME(t) : ToNumber(sec); | 584 sec = argc < 3 ? LOCAL_SEC(this) : ToNumber(sec); |
855 ms = argc < 4 ? NAN_OR_MS_FROM_TIME(t) : ToNumber(ms); | 585 ms = argc < 4 ? LOCAL_MS(this) : ToNumber(ms); |
856 var time = MakeTime(hour, min, sec, ms); | 586 var time = MakeTime(hour, min, sec, ms); |
857 return %_SetValueOf(this, TimeClip(UTC(MakeDate(DAY(t), time)))); | 587 return SET_LOCAL_DATE_VALUE(this, MakeDate(LOCAL_DAYS(this), time)); |
858 } | 588 } |
859 | 589 |
860 | 590 |
861 // ECMA 262 - 15.9.5.34 | 591 // ECMA 262 - 15.9.5.34 |
862 function DateSetUTCHours(hour, min, sec, ms) { | 592 function DateSetUTCHours(hour, min, sec, ms) { |
863 var t = DATE_VALUE(this); | 593 CHECK_DATE(this); |
| 594 var t = UTC_DATE_VALUE(this); |
864 hour = ToNumber(hour); | 595 hour = ToNumber(hour); |
865 var argc = %_ArgumentsLength(); | 596 var argc = %_ArgumentsLength(); |
866 min = argc < 2 ? NAN_OR_MIN_FROM_TIME(t) : ToNumber(min); | 597 min = argc < 2 ? UTC_MIN(this) : ToNumber(min); |
867 sec = argc < 3 ? NAN_OR_SEC_FROM_TIME(t) : ToNumber(sec); | 598 sec = argc < 3 ? UTC_SEC(this) : ToNumber(sec); |
868 ms = argc < 4 ? NAN_OR_MS_FROM_TIME(t) : ToNumber(ms); | 599 ms = argc < 4 ? UTC_MS(this) : ToNumber(ms); |
869 var time = MakeTime(hour, min, sec, ms); | 600 var time = MakeTime(hour, min, sec, ms); |
870 return %_SetValueOf(this, TimeClip(MakeDate(DAY(t), time))); | 601 return SET_UTC_DATE_VALUE(this, MakeDate(UTC_DAYS(this), time)); |
871 } | 602 } |
872 | 603 |
873 | 604 |
874 // ECMA 262 - 15.9.5.36 | 605 // ECMA 262 - 15.9.5.36 |
875 function DateSetDate(date) { | 606 function DateSetDate(date) { |
876 var t = LocalTime(DATE_VALUE(this)); | 607 CHECK_DATE(this); |
| 608 var t = LOCAL_DATE_VALUE(this); |
877 date = ToNumber(date); | 609 date = ToNumber(date); |
878 var day = MakeDay(YearFromTime(t), MonthFromTime(t), date); | 610 var day = MakeDay(LOCAL_YEAR(this), LOCAL_MONTH(this), date); |
879 return %_SetValueOf(this, TimeClip(UTC(MakeDate(day, TimeWithinDay(t))))); | 611 return SET_LOCAL_DATE_VALUE(this, MakeDate(day, LOCAL_TIME_IN_DAY(this))); |
880 } | 612 } |
881 | 613 |
882 | 614 |
883 // ECMA 262 - 15.9.5.37 | 615 // ECMA 262 - 15.9.5.37 |
884 function DateSetUTCDate(date) { | 616 function DateSetUTCDate(date) { |
885 var t = DATE_VALUE(this); | 617 CHECK_DATE(this); |
| 618 var t = UTC_DATE_VALUE(this); |
886 date = ToNumber(date); | 619 date = ToNumber(date); |
887 var day = MakeDay(YearFromTime(t), MonthFromTime(t), date); | 620 var day = MakeDay(UTC_YEAR(this), UTC_MONTH(this), date); |
888 return %_SetValueOf(this, TimeClip(MakeDate(day, TimeWithinDay(t)))); | 621 return SET_UTC_DATE_VALUE(this, MakeDate(day, UTC_TIME_IN_DAY(this))); |
889 } | 622 } |
890 | 623 |
891 | 624 |
892 // ECMA 262 - 15.9.5.38 | 625 // ECMA 262 - 15.9.5.38 |
893 function DateSetMonth(month, date) { | 626 function DateSetMonth(month, date) { |
894 var t = LocalTime(DATE_VALUE(this)); | 627 CHECK_DATE(this); |
| 628 var t = LOCAL_DATE_VALUE(this); |
895 month = ToNumber(month); | 629 month = ToNumber(month); |
896 date = %_ArgumentsLength() < 2 ? NAN_OR_DATE_FROM_TIME(t) : ToNumber(date); | 630 date = %_ArgumentsLength() < 2 ? LOCAL_DAY(this) : ToNumber(date); |
897 var day = MakeDay(YearFromTime(t), month, date); | 631 var day = MakeDay(LOCAL_YEAR(this), month, date); |
898 return %_SetValueOf(this, TimeClip(UTC(MakeDate(day, TimeWithinDay(t))))); | 632 return SET_LOCAL_DATE_VALUE(this, MakeDate(day, LOCAL_TIME_IN_DAY(this))); |
899 } | 633 } |
900 | 634 |
901 | 635 |
902 // ECMA 262 - 15.9.5.39 | 636 // ECMA 262 - 15.9.5.39 |
903 function DateSetUTCMonth(month, date) { | 637 function DateSetUTCMonth(month, date) { |
904 var t = DATE_VALUE(this); | 638 CHECK_DATE(this); |
| 639 var t = UTC_DATE_VALUE(this); |
905 month = ToNumber(month); | 640 month = ToNumber(month); |
906 date = %_ArgumentsLength() < 2 ? NAN_OR_DATE_FROM_TIME(t) : ToNumber(date); | 641 date = %_ArgumentsLength() < 2 ? UTC_DAY(this) : ToNumber(date); |
907 var day = MakeDay(YearFromTime(t), month, date); | 642 var day = MakeDay(UTC_YEAR(this), month, date); |
908 return %_SetValueOf(this, TimeClip(MakeDate(day, TimeWithinDay(t)))); | 643 return SET_UTC_DATE_VALUE(this, MakeDate(day, UTC_TIME_IN_DAY(this))); |
909 } | 644 } |
910 | 645 |
911 | 646 |
912 // ECMA 262 - 15.9.5.40 | 647 // ECMA 262 - 15.9.5.40 |
913 function DateSetFullYear(year, month, date) { | 648 function DateSetFullYear(year, month, date) { |
914 var t = DATE_VALUE(this); | 649 CHECK_DATE(this); |
915 t = NUMBER_IS_NAN(t) ? 0 : LocalTimeNoCheck(t); | 650 var t = LOCAL_DATE_VALUE(this); |
916 year = ToNumber(year); | 651 year = ToNumber(year); |
917 var argc = %_ArgumentsLength(); | 652 var argc = %_ArgumentsLength(); |
918 month = argc < 2 ? MonthFromTime(t) : ToNumber(month); | 653 var time ; |
919 date = argc < 3 ? DateFromTime(t) : ToNumber(date); | 654 if (NUMBER_IS_NAN(t)) { |
| 655 month = argc < 2 ? 0 : ToNumber(month); |
| 656 date = argc < 3 ? 1 : ToNumber(date); |
| 657 time = 0; |
| 658 } else { |
| 659 month = argc < 2 ? LOCAL_MONTH(this) : ToNumber(month); |
| 660 date = argc < 3 ? LOCAL_DAY(this) : ToNumber(date); |
| 661 time = LOCAL_TIME_IN_DAY(this); |
| 662 } |
920 var day = MakeDay(year, month, date); | 663 var day = MakeDay(year, month, date); |
921 return %_SetValueOf(this, TimeClip(UTC(MakeDate(day, TimeWithinDay(t))))); | 664 return SET_LOCAL_DATE_VALUE(this, MakeDate(day, time)); |
922 } | 665 } |
923 | 666 |
924 | 667 |
925 // ECMA 262 - 15.9.5.41 | 668 // ECMA 262 - 15.9.5.41 |
926 function DateSetUTCFullYear(year, month, date) { | 669 function DateSetUTCFullYear(year, month, date) { |
927 var t = DATE_VALUE(this); | 670 CHECK_DATE(this); |
928 if (NUMBER_IS_NAN(t)) t = 0; | 671 var t = UTC_DATE_VALUE(this); |
929 var argc = %_ArgumentsLength(); | |
930 year = ToNumber(year); | 672 year = ToNumber(year); |
931 month = argc < 2 ? MonthFromTime(t) : ToNumber(month); | 673 var argc = %_ArgumentsLength(); |
932 date = argc < 3 ? DateFromTime(t) : ToNumber(date); | 674 var time ; |
| 675 if (NUMBER_IS_NAN(t)) { |
| 676 month = argc < 2 ? 0 : ToNumber(month); |
| 677 date = argc < 3 ? 1 : ToNumber(date); |
| 678 time = 0; |
| 679 } else { |
| 680 month = argc < 2 ? UTC_MONTH(this) : ToNumber(month); |
| 681 date = argc < 3 ? UTC_DAY(this) : ToNumber(date); |
| 682 time = UTC_TIME_IN_DAY(this); |
| 683 } |
933 var day = MakeDay(year, month, date); | 684 var day = MakeDay(year, month, date); |
934 return %_SetValueOf(this, TimeClip(MakeDate(day, TimeWithinDay(t)))); | 685 return SET_UTC_DATE_VALUE(this, MakeDate(day, time)); |
935 } | 686 } |
936 | 687 |
937 | 688 |
938 // ECMA 262 - 15.9.5.42 | 689 // ECMA 262 - 15.9.5.42 |
939 function DateToUTCString() { | 690 function DateToUTCString() { |
940 var t = DATE_VALUE(this); | 691 CHECK_DATE(this); |
| 692 var t = UTC_DATE_VALUE(this); |
941 if (NUMBER_IS_NAN(t)) return kInvalidDate; | 693 if (NUMBER_IS_NAN(t)) return kInvalidDate; |
942 // Return UTC string of the form: Sat, 31 Jan 1970 23:00:00 GMT | 694 // Return UTC string of the form: Sat, 31 Jan 1970 23:00:00 GMT |
943 return WeekDays[WeekDay(t)] + ', ' | 695 return WeekDays[UTC_WEEKDAY(this)] + ', ' |
944 + TwoDigitString(DateFromTime(t)) + ' ' | 696 + TwoDigitString(UTC_DAY(this)) + ' ' |
945 + Months[MonthFromTime(t)] + ' ' | 697 + Months[UTC_MONTH(this)] + ' ' |
946 + YearFromTime(t) + ' ' | 698 + UTC_YEAR(this) + ' ' |
947 + TimeString(t) + ' GMT'; | 699 + TimeString(t) + ' GMT'; |
948 } | 700 } |
949 | 701 |
950 | 702 |
951 // ECMA 262 - B.2.4 | 703 // ECMA 262 - B.2.4 |
952 function DateGetYear() { | 704 function DateGetYear() { |
953 var t = DATE_VALUE(this); | 705 CHECK_DATE(this); |
954 if (NUMBER_IS_NAN(t)) return $NaN; | 706 return LOCAL_YEAR(this) - 1900; |
955 return YearFromTime(LocalTimeNoCheck(t)) - 1900; | |
956 } | 707 } |
957 | 708 |
958 | 709 |
959 // ECMA 262 - B.2.5 | 710 // ECMA 262 - B.2.5 |
960 function DateSetYear(year) { | 711 function DateSetYear(year) { |
961 var t = LocalTime(DATE_VALUE(this)); | 712 CHECK_DATE(this); |
962 if (NUMBER_IS_NAN(t)) t = 0; | |
963 year = ToNumber(year); | 713 year = ToNumber(year); |
964 if (NUMBER_IS_NAN(year)) return %_SetValueOf(this, $NaN); | 714 if (NUMBER_IS_NAN(year)) return SET_UTC_DATE_VALUE(this, $NaN); |
965 year = (0 <= TO_INTEGER(year) && TO_INTEGER(year) <= 99) | 715 year = (0 <= TO_INTEGER(year) && TO_INTEGER(year) <= 99) |
966 ? 1900 + TO_INTEGER(year) : year; | 716 ? 1900 + TO_INTEGER(year) : year; |
967 var day = MakeDay(year, MonthFromTime(t), DateFromTime(t)); | 717 var t = LOCAL_DATE_VALUE(this); |
968 return %_SetValueOf(this, TimeClip(UTC(MakeDate(day, TimeWithinDay(t))))); | 718 var month, date, time; |
969 } | 719 if (NUMBER_IS_NAN(t)) { |
970 | 720 month = 0; |
971 | 721 date = 1; |
| 722 time = 0; |
| 723 } else { |
| 724 month = LOCAL_MONTH(this); |
| 725 date = LOCAL_DAY(this); |
| 726 time = TimeWithinDay(t); |
| 727 } |
| 728 var day = MakeDay(year, month, date); |
| 729 return SET_LOCAL_DATE_VALUE(this, MakeDate(day, time)); |
| 730 } |
| 731 |
| 732 |
972 // ECMA 262 - B.2.6 | 733 // ECMA 262 - B.2.6 |
973 // | 734 // |
974 // Notice that this does not follow ECMA 262 completely. ECMA 262 | 735 // Notice that this does not follow ECMA 262 completely. ECMA 262 |
975 // says that toGMTString should be the same Function object as | 736 // says that toGMTString should be the same Function object as |
976 // toUTCString. JSC does not do this, so for compatibility we do not | 737 // toUTCString. JSC does not do this, so for compatibility we do not |
977 // do that either. Instead, we create a new function whose name | 738 // do that either. Instead, we create a new function whose name |
978 // property will return toGMTString. | 739 // property will return toGMTString. |
979 function DateToGMTString() { | 740 function DateToGMTString() { |
980 return %_CallFunction(this, DateToUTCString); | 741 return %_CallFunction(this, DateToUTCString); |
981 } | 742 } |
982 | 743 |
983 | 744 |
984 function PadInt(n, digits) { | 745 function PadInt(n, digits) { |
985 if (digits == 1) return n; | 746 if (digits == 1) return n; |
986 return n < MathPow(10, digits - 1) ? '0' + PadInt(n, digits - 1) : n; | 747 return n < MathPow(10, digits - 1) ? '0' + PadInt(n, digits - 1) : n; |
987 } | 748 } |
988 | 749 |
989 | 750 |
990 // ECMA 262 - 15.9.5.43 | 751 // ECMA 262 - 15.9.5.43 |
991 function DateToISOString() { | 752 function DateToISOString() { |
992 var t = DATE_VALUE(this); | 753 CHECK_DATE(this); |
| 754 var t = UTC_DATE_VALUE(this); |
993 if (NUMBER_IS_NAN(t)) throw MakeRangeError("invalid_time_value", []); | 755 if (NUMBER_IS_NAN(t)) throw MakeRangeError("invalid_time_value", []); |
994 var year = this.getUTCFullYear(); | 756 var year = this.getUTCFullYear(); |
995 var year_string; | 757 var year_string; |
996 if (year >= 0 && year <= 9999) { | 758 if (year >= 0 && year <= 9999) { |
997 year_string = PadInt(year, 4); | 759 year_string = PadInt(year, 4); |
998 } else { | 760 } else { |
999 if (year < 0) { | 761 if (year < 0) { |
1000 year_string = "-" + PadInt(-year, 6); | 762 year_string = "-" + PadInt(-year, 6); |
1001 } else { | 763 } else { |
1002 year_string = "+" + PadInt(year, 6); | 764 year_string = "+" + PadInt(year, 6); |
(...skipping 14 matching lines...) Expand all Loading... |
1017 var o = ToObject(this); | 779 var o = ToObject(this); |
1018 var tv = DefaultNumber(o); | 780 var tv = DefaultNumber(o); |
1019 if (IS_NUMBER(tv) && !NUMBER_IS_FINITE(tv)) { | 781 if (IS_NUMBER(tv) && !NUMBER_IS_FINITE(tv)) { |
1020 return null; | 782 return null; |
1021 } | 783 } |
1022 return o.toISOString(); | 784 return o.toISOString(); |
1023 } | 785 } |
1024 | 786 |
1025 | 787 |
1026 function ResetDateCache() { | 788 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: | 789 // Reset the timezone cache: |
1040 timezone_cache_time = $NaN; | 790 timezone_cache_time = $NaN; |
1041 timezone_cache_timezone = undefined; | 791 timezone_cache_timezone = undefined; |
1042 | 792 |
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: | 793 // Reset the date cache: |
1052 cache = Date_cache; | 794 cache = Date_cache; |
1053 cache.time = $NaN; | 795 cache.time = $NaN; |
1054 cache.year = $NaN; | |
1055 cache.string = null; | 796 cache.string = null; |
1056 } | 797 } |
1057 | 798 |
1058 | 799 |
1059 // ------------------------------------------------------------------- | 800 // ------------------------------------------------------------------- |
1060 | 801 |
1061 function SetUpDate() { | 802 function SetUpDate() { |
1062 %CheckIsBootstrapping(); | 803 %CheckIsBootstrapping(); |
1063 // Set up non-enumerable properties of the Date object itself. | 804 // Set up non-enumerable properties of the Date object itself. |
1064 InstallFunctions($Date, DONT_ENUM, $Array( | 805 InstallFunctions($Date, DONT_ENUM, $Array( |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1116 "toGMTString", DateToGMTString, | 857 "toGMTString", DateToGMTString, |
1117 "toUTCString", DateToUTCString, | 858 "toUTCString", DateToUTCString, |
1118 "getYear", DateGetYear, | 859 "getYear", DateGetYear, |
1119 "setYear", DateSetYear, | 860 "setYear", DateSetYear, |
1120 "toISOString", DateToISOString, | 861 "toISOString", DateToISOString, |
1121 "toJSON", DateToJSON | 862 "toJSON", DateToJSON |
1122 )); | 863 )); |
1123 } | 864 } |
1124 | 865 |
1125 SetUpDate(); | 866 SetUpDate(); |
OLD | NEW |