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 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
114 // the actual year if it is in the range 1970..2037 | 114 // the actual year if it is in the range 1970..2037 |
115 if (t >= 0 && t <= 2.1e12) return t; | 115 if (t >= 0 && t <= 2.1e12) return t; |
116 | 116 |
117 var day = MakeDay(EquivalentYear(YEAR_FROM_TIME(t)), | 117 var day = MakeDay(EquivalentYear(YEAR_FROM_TIME(t)), |
118 MONTH_FROM_TIME(t), | 118 MONTH_FROM_TIME(t), |
119 DATE_FROM_TIME(t)); | 119 DATE_FROM_TIME(t)); |
120 return MakeDate(day, TimeWithinDay(t)); | 120 return MakeDate(day, TimeWithinDay(t)); |
121 } | 121 } |
122 | 122 |
123 | 123 |
124 // Because computing the DST offset is a pretty expensive operation | 124 // local_time_offset is initialized when the DST_offset_cache is missed. |
125 // we keep a cache of last computed offset along with a time interval | 125 // It must not be used until after a call to DaylightSavingsOffset(). |
| 126 // In this way, only one check, for a DST cache miss, is needed. |
| 127 var local_time_offset; |
| 128 |
| 129 |
| 130 // Because computing the DST offset is an expensive operation, |
| 131 // we keep a cache of the last computed DST offset along with a time interval |
126 // where we know the cache is valid. | 132 // where we know the cache is valid. |
| 133 // When the cache is valid, local_time_offset is also valid. |
127 var DST_offset_cache = { | 134 var DST_offset_cache = { |
128 // Cached DST offset. | 135 // Cached DST offset. |
129 offset: 0, | 136 offset: 0, |
130 // Time interval where the cached offset is valid. | 137 // Time interval where the cached offset is valid. |
131 start: 0, end: -1, | 138 start: 0, end: -1, |
132 // Size of next interval expansion. | 139 // Size of next interval expansion. |
133 increment: 0 | 140 increment: 0 |
134 }; | 141 }; |
135 | 142 |
136 | 143 |
137 // NOTE: The implementation relies on the fact that no time zones have | 144 // NOTE: The implementation relies on the fact that no time zones have |
138 // more than one daylight savings offset change per month. | 145 // more than one daylight savings offset change per month. |
139 // If this function is called with NaN it returns NaN. | 146 // If this function is called with NaN it returns NaN. |
140 function DaylightSavingsOffset(t) { | 147 function DaylightSavingsOffset(t) { |
141 // Load the cache object from the builtins object. | 148 // Load the cache object from the builtins object. |
142 var cache = DST_offset_cache; | 149 var cache = DST_offset_cache; |
143 | 150 |
144 // Cache the start and the end in local variables for fast access. | 151 // Cache the start and the end in local variables for fast access. |
145 var start = cache.start; | 152 var start = cache.start; |
146 var end = cache.end; | 153 var end = cache.end; |
147 | 154 |
148 if (start <= t) { | 155 if (start <= t) { |
149 // If the time fits in the cached interval, return the cached offset. | 156 // If the time fits in the cached interval, return the cached offset. |
150 if (t <= end) return cache.offset; | 157 if (t <= end) return cache.offset; |
151 | 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 |
152 // Compute a possible new interval end. | 164 // Compute a possible new interval end. |
153 var new_end = end + cache.increment; | 165 var new_end = end + cache.increment; |
154 | 166 |
155 if (t <= new_end) { | 167 if (t <= new_end) { |
156 var end_offset = %DateDaylightSavingsOffset(EquivalentTime(new_end)); | 168 var end_offset = %DateDaylightSavingsOffset(EquivalentTime(new_end)); |
157 if (cache.offset == end_offset) { | 169 if (cache.offset == end_offset) { |
158 // If the offset at the end of the new interval still matches | 170 // If the offset at the end of the new interval still matches |
159 // the offset in the cache, we grow the cached time interval | 171 // the offset in the cache, we grow the cached time interval |
160 // and return the offset. | 172 // and return the offset. |
161 cache.end = new_end; | 173 cache.end = new_end; |
(...skipping 16 matching lines...) Expand all Loading... |
178 cache.increment /= 3; | 190 cache.increment /= 3; |
179 cache.end = t; | 191 cache.end = t; |
180 } | 192 } |
181 // Update the offset in the cache and return it. | 193 // Update the offset in the cache and return it. |
182 cache.offset = offset; | 194 cache.offset = offset; |
183 return offset; | 195 return offset; |
184 } | 196 } |
185 } | 197 } |
186 } | 198 } |
187 | 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 } |
188 // Compute the DST offset for the time and shrink the cache interval | 204 // Compute the DST offset for the time and shrink the cache interval |
189 // to only contain the time. This allows fast repeated DST offset | 205 // to only contain the time. This allows fast repeated DST offset |
190 // computations for the same time. | 206 // computations for the same time. |
191 var offset = %DateDaylightSavingsOffset(EquivalentTime(t)); | 207 var offset = %DateDaylightSavingsOffset(EquivalentTime(t)); |
192 cache.offset = offset; | 208 cache.offset = offset; |
193 cache.start = cache.end = t; | 209 cache.start = cache.end = t; |
194 cache.increment = msPerMonth; | 210 cache.increment = msPerMonth; |
195 return offset; | 211 return offset; |
196 } | 212 } |
197 | 213 |
(...skipping 10 matching lines...) Expand all Loading... |
208 timezone_cache_time = t; | 224 timezone_cache_time = t; |
209 timezone_cache_timezone = timezone; | 225 timezone_cache_timezone = timezone; |
210 return timezone; | 226 return timezone; |
211 } | 227 } |
212 | 228 |
213 | 229 |
214 function WeekDay(time) { | 230 function WeekDay(time) { |
215 return Modulo(DAY(time) + 4, 7); | 231 return Modulo(DAY(time) + 4, 7); |
216 } | 232 } |
217 | 233 |
218 var local_time_offset = %DateLocalTimeOffset(); | |
219 | 234 |
220 function LocalTime(time) { | 235 function LocalTime(time) { |
221 if (NUMBER_IS_NAN(time)) return time; | 236 if (NUMBER_IS_NAN(time)) return time; |
222 return time + local_time_offset + DaylightSavingsOffset(time); | 237 // DaylightSavingsOffset called before local_time_offset used. |
| 238 return time + DaylightSavingsOffset(time) + local_time_offset; |
223 } | 239 } |
224 | 240 |
225 function LocalTimeNoCheck(time) { | 241 function LocalTimeNoCheck(time) { |
226 if (time < -MAX_TIME_MS || time > MAX_TIME_MS) { | 242 if (time < -MAX_TIME_MS || time > MAX_TIME_MS) { |
227 return $NaN; | 243 return $NaN; |
228 } | 244 } |
229 | 245 |
230 // Inline the DST offset cache checks for speed. | 246 // Inline the DST offset cache checks for speed. |
| 247 // The cache is hit, or DaylightSavingsOffset is called, |
| 248 // before local_time_offset is used. |
231 var cache = DST_offset_cache; | 249 var cache = DST_offset_cache; |
232 if (cache.start <= time && time <= cache.end) { | 250 if (cache.start <= time && time <= cache.end) { |
233 var dst_offset = cache.offset; | 251 var dst_offset = cache.offset; |
234 } else { | 252 } else { |
235 var dst_offset = DaylightSavingsOffset(time); | 253 var dst_offset = DaylightSavingsOffset(time); |
236 } | 254 } |
237 return time + local_time_offset + dst_offset; | 255 return time + local_time_offset + dst_offset; |
238 } | 256 } |
239 | 257 |
240 | 258 |
241 function UTC(time) { | 259 function UTC(time) { |
242 if (NUMBER_IS_NAN(time)) return time; | 260 if (NUMBER_IS_NAN(time)) return time; |
| 261 // local_time_offset is needed before the call to DaylightSavingsOffset, |
| 262 // so it may be uninitialized. |
| 263 if (IS_UNDEFINED(local_time_offset)) { |
| 264 local_time_offset = %DateLocalTimeOffset(); |
| 265 } |
243 var tmp = time - local_time_offset; | 266 var tmp = time - local_time_offset; |
244 return tmp - DaylightSavingsOffset(tmp); | 267 return tmp - DaylightSavingsOffset(tmp); |
245 } | 268 } |
246 | 269 |
247 | 270 |
248 // ECMA 262 - 15.9.1.11 | 271 // ECMA 262 - 15.9.1.11 |
249 function MakeTime(hour, min, sec, ms) { | 272 function MakeTime(hour, min, sec, ms) { |
250 if (!$isFinite(hour)) return $NaN; | 273 if (!$isFinite(hour)) return $NaN; |
251 if (!$isFinite(min)) return $NaN; | 274 if (!$isFinite(min)) return $NaN; |
252 if (!$isFinite(sec)) return $NaN; | 275 if (!$isFinite(sec)) return $NaN; |
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
559 | 582 |
560 function TimeString(time) { | 583 function TimeString(time) { |
561 return TwoDigitString(HOUR_FROM_TIME(time)) + ':' | 584 return TwoDigitString(HOUR_FROM_TIME(time)) + ':' |
562 + TwoDigitString(MIN_FROM_TIME(time)) + ':' | 585 + TwoDigitString(MIN_FROM_TIME(time)) + ':' |
563 + TwoDigitString(SEC_FROM_TIME(time)); | 586 + TwoDigitString(SEC_FROM_TIME(time)); |
564 } | 587 } |
565 | 588 |
566 | 589 |
567 function LocalTimezoneString(time) { | 590 function LocalTimezoneString(time) { |
568 var timezoneOffset = | 591 var timezoneOffset = |
569 (local_time_offset + DaylightSavingsOffset(time)) / msPerMinute; | 592 (DaylightSavingsOffset(time) + local_time_offset) / msPerMinute; |
570 var sign = (timezoneOffset >= 0) ? 1 : -1; | 593 var sign = (timezoneOffset >= 0) ? 1 : -1; |
571 var hours = FLOOR((sign * timezoneOffset)/60); | 594 var hours = FLOOR((sign * timezoneOffset)/60); |
572 var min = FLOOR((sign * timezoneOffset)%60); | 595 var min = FLOOR((sign * timezoneOffset)%60); |
573 var gmt = ' GMT' + ((sign == 1) ? '+' : '-') + | 596 var gmt = ' GMT' + ((sign == 1) ? '+' : '-') + |
574 TwoDigitString(hours) + TwoDigitString(min); | 597 TwoDigitString(hours) + TwoDigitString(min); |
575 return gmt + ' (' + LocalTimezone(time) + ')'; | 598 return gmt + ' (' + LocalTimezone(time) + ')'; |
576 } | 599 } |
577 | 600 |
578 | 601 |
579 function DatePrintString(time) { | 602 function DatePrintString(time) { |
(...skipping 501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1081 "toGMTString", DateToGMTString, | 1104 "toGMTString", DateToGMTString, |
1082 "toUTCString", DateToUTCString, | 1105 "toUTCString", DateToUTCString, |
1083 "getYear", DateGetYear, | 1106 "getYear", DateGetYear, |
1084 "setYear", DateSetYear, | 1107 "setYear", DateSetYear, |
1085 "toISOString", DateToISOString, | 1108 "toISOString", DateToISOString, |
1086 "toJSON", DateToJSON | 1109 "toJSON", DateToJSON |
1087 )); | 1110 )); |
1088 } | 1111 } |
1089 | 1112 |
1090 SetupDate(); | 1113 SetupDate(); |
OLD | NEW |