Chromium Code Reviews| Index: src/date-delay.js |
| =================================================================== |
| --- src/date-delay.js (revision 2174) |
| +++ src/date-delay.js (working copy) |
| @@ -115,7 +115,7 @@ |
| // - leap year. |
| // - week day of first day. |
| var time = TimeFromYear(year); |
| - var recent_year = (InLeapYear(time) == 0 ? 1967 : 1956) + |
| + var recent_year = (InLeapYear(time) == 0 ? 1967 : 1956) + |
| (WeekDay(time) * 12) % 28; |
| // Find the year in the range 2008..2037 that is equivalent mod 28. |
| // Add 3*28 to give a positive argument to the modulus operator. |
| @@ -129,23 +129,82 @@ |
| // (measured in whole seconds based on the 1970 epoch). |
| // We solve this by mapping the time to a year with same leap-year-ness |
| // and same starting day for the year. The ECMAscript specification says |
| - // we must do this, but for compatability with other browsers, we use |
| + // we must do this, but for compatibility with other browsers, we use |
| // the actual year if it is in the range 1970..2037 |
| if (t >= 0 && t <= 2.1e12) return t; |
| var day = MakeDay(EquivalentYear(YearFromTime(t)), MonthFromTime(t), DateFromTime(t)); |
| return TimeClip(MakeDate(day, TimeWithinDay(t))); |
| } |
| -var daylight_cache_time = $NaN; |
| -var daylight_cache_offset; |
| +// Because computing the DST offset is a pretty expensive operation |
| +// we keep a cache of last computed offset along with a time interval |
| +// where we know the cache is valid. |
| +var DST_offset_cache = { |
| + // Cached DST offset. |
| + offset: 0, |
| + // Time interval where the cached offset is valid. |
| + start: 0, end: -1, |
| + // Size of next interval expansion. |
| + increment: 0 |
| +}; |
| + |
| + |
| function DaylightSavingsOffset(t) { |
|
William Hesse
2009/06/16 07:11:29
Comment the function to state that the algorithm i
|
| - if (t == daylight_cache_time) { |
| - return daylight_cache_offset; |
| + // Load the cache object from the builtins object. |
| + var cache = DST_offset_cache; |
| + |
| + // Cache the start and the end in local variables for fast access. |
| + var start = cache.start; |
| + var end = cache.end; |
| + |
| + if (start <= t) { |
| + // If the time fits in the cached interval, return the cached offset. |
| + if (t <= end) return cache.offset; |
| + |
| + // Compute a possible new interval end. |
| + var new_end = end + cache.increment; |
| + |
| + if (t <= new_end) { |
| + var end_offset = %DateDaylightSavingsOffset(EquivalentTime(new_end)); |
| + if (cache.offset == end_offset) { |
| + // If the offset at the end of the new interval still matches |
| + // the offset in the cache, we grow the cached time interval |
| + // and return the offset. |
| + cache.end = new_end; |
| + cache.increment = msPerMonth; |
| + return end_offset; |
| + } else { |
| + var offset = %DateDaylightSavingsOffset(EquivalentTime(t)); |
| + if (offset == end_offset) { |
| + // The offset at the given time is equal to the offset at the |
| + // new end of the interval, so that means that we've just skipped |
| + // the point in time where the DST offset change occurred. Updated |
| + // the interval to reflect this and reset the increment. |
| + cache.start = t; |
| + cache.end = new_end; |
| + cache.increment = msPerMonth; |
| + } else { |
| + // The interval contains a DST offset change and the given time is |
| + // before it. Adjust the increment to avoid a linear search for |
| + // the offset change point and change the end of the interval. |
| + cache.increment /= 3; |
| + cache.end = t; |
| + } |
| + // Update the offset in the cache and return it. |
| + cache.offset = offset; |
| + return offset; |
| + } |
| + } |
| } |
| + |
| + // Compute the DST offset for the time and shrink the cache interval |
| + // to only contain the time. This allows fast repeated DST offset |
| + // computations for the same time. |
| var offset = %DateDaylightSavingsOffset(EquivalentTime(t)); |
| - daylight_cache_time = t; |
| - daylight_cache_offset = offset; |
| + cache.offset = offset; |
| + cache.start = cache.end = t; |
| + cache.increment = msPerMonth; |
| return offset; |
| } |
| @@ -154,7 +213,7 @@ |
| var timezone_cache_timezone; |
| function LocalTimezone(t) { |
| - if(t == timezone_cache_time) { |
| + if (t == timezone_cache_time) { |
| return timezone_cache_timezone; |
| } |
| var timezone = %DateLocalTimezone(EquivalentTime(t)); |