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