| 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 // Inline the DST offset cache checks for speed. | 242 // Inline the DST offset cache checks for speed. |
| 243 // The cache is hit, or DaylightSavingsOffset is called, |
| 244 // before local_time_offset is used. |
| 227 var cache = DST_offset_cache; | 245 var cache = DST_offset_cache; |
| 228 if (cache.start <= time && time <= cache.end) { | 246 if (cache.start <= time && time <= cache.end) { |
| 229 var dst_offset = cache.offset; | 247 var dst_offset = cache.offset; |
| 230 } else { | 248 } else { |
| 231 var dst_offset = DaylightSavingsOffset(time); | 249 var dst_offset = DaylightSavingsOffset(time); |
| 232 } | 250 } |
| 233 return time + local_time_offset + dst_offset; | 251 return time + local_time_offset + dst_offset; |
| 234 } | 252 } |
| 235 | 253 |
| 236 | 254 |
| 237 function UTC(time) { | 255 function UTC(time) { |
| 238 if (NUMBER_IS_NAN(time)) return time; | 256 if (NUMBER_IS_NAN(time)) return time; |
| 257 // local_time_offset is needed before the call to DaylightSavingsOffset, |
| 258 // so it may be uninitialized. |
| 259 if (IS_UNDEFINED(local_time_offset)) { |
| 260 local_time_offset = %DateLocalTimeOffset(); |
| 261 } |
| 239 var tmp = time - local_time_offset; | 262 var tmp = time - local_time_offset; |
| 240 return tmp - DaylightSavingsOffset(tmp); | 263 return tmp - DaylightSavingsOffset(tmp); |
| 241 } | 264 } |
| 242 | 265 |
| 243 | 266 |
| 244 // ECMA 262 - 15.9.1.11 | 267 // ECMA 262 - 15.9.1.11 |
| 245 function MakeTime(hour, min, sec, ms) { | 268 function MakeTime(hour, min, sec, ms) { |
| 246 if (!$isFinite(hour)) return $NaN; | 269 if (!$isFinite(hour)) return $NaN; |
| 247 if (!$isFinite(min)) return $NaN; | 270 if (!$isFinite(min)) return $NaN; |
| 248 if (!$isFinite(sec)) return $NaN; | 271 if (!$isFinite(sec)) return $NaN; |
| (...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 557 | 580 |
| 558 | 581 |
| 559 function TimeString(time) { | 582 function TimeString(time) { |
| 560 return TwoDigitString(HOUR_FROM_TIME(time)) + ':' | 583 return TwoDigitString(HOUR_FROM_TIME(time)) + ':' |
| 561 + TwoDigitString(MIN_FROM_TIME(time)) + ':' | 584 + TwoDigitString(MIN_FROM_TIME(time)) + ':' |
| 562 + TwoDigitString(SEC_FROM_TIME(time)); | 585 + TwoDigitString(SEC_FROM_TIME(time)); |
| 563 } | 586 } |
| 564 | 587 |
| 565 | 588 |
| 566 function LocalTimezoneString(time) { | 589 function LocalTimezoneString(time) { |
| 590 var old_timezone = timezone_cache_timezone; |
| 591 var timezone = LocalTimezone(time); |
| 592 if (old_timezone && timezone != old_timezone) { |
| 593 // If the timezone string has changed from the one that we cached, |
| 594 // the local time offset may now be wrong. So we need to update it |
| 595 // and try again. |
| 596 local_time_offset = %DateLocalTimeOffset(); |
| 597 // We also need to invalidate the DST cache as the new timezone may have |
| 598 // different DST times. |
| 599 var dst_cache = DST_offset_cache; |
| 600 dst_cache.start = 0; |
| 601 dst_cache.end = -1; |
| 602 } |
| 603 |
| 567 var timezoneOffset = | 604 var timezoneOffset = |
| 568 (local_time_offset + DaylightSavingsOffset(time)) / msPerMinute; | 605 (DaylightSavingsOffset(time) + local_time_offset) / msPerMinute; |
| 569 var sign = (timezoneOffset >= 0) ? 1 : -1; | 606 var sign = (timezoneOffset >= 0) ? 1 : -1; |
| 570 var hours = FLOOR((sign * timezoneOffset)/60); | 607 var hours = FLOOR((sign * timezoneOffset)/60); |
| 571 var min = FLOOR((sign * timezoneOffset)%60); | 608 var min = FLOOR((sign * timezoneOffset)%60); |
| 572 var gmt = ' GMT' + ((sign == 1) ? '+' : '-') + | 609 var gmt = ' GMT' + ((sign == 1) ? '+' : '-') + |
| 573 TwoDigitString(hours) + TwoDigitString(min); | 610 TwoDigitString(hours) + TwoDigitString(min); |
| 574 return gmt + ' (' + LocalTimezone(time) + ')'; | 611 return gmt + ' (' + timezone + ')'; |
| 575 } | 612 } |
| 576 | 613 |
| 577 | 614 |
| 578 function DatePrintString(time) { | 615 function DatePrintString(time) { |
| 579 return DateString(time) + ' ' + TimeString(time); | 616 return DateString(time) + ' ' + TimeString(time); |
| 580 } | 617 } |
| 581 | 618 |
| 582 // ------------------------------------------------------------------- | 619 // ------------------------------------------------------------------- |
| 583 | 620 |
| 584 // Reused output buffer. Used when parsing date strings. | 621 // Reused output buffer. Used when parsing date strings. |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 623 // elapsed since 1 January 1970 00:00:00 UTC. | 660 // elapsed since 1 January 1970 00:00:00 UTC. |
| 624 function DateNow() { | 661 function DateNow() { |
| 625 return %DateCurrentTime(); | 662 return %DateCurrentTime(); |
| 626 } | 663 } |
| 627 | 664 |
| 628 | 665 |
| 629 // ECMA 262 - 15.9.5.2 | 666 // ECMA 262 - 15.9.5.2 |
| 630 function DateToString() { | 667 function DateToString() { |
| 631 var t = DATE_VALUE(this); | 668 var t = DATE_VALUE(this); |
| 632 if (NUMBER_IS_NAN(t)) return kInvalidDate; | 669 if (NUMBER_IS_NAN(t)) return kInvalidDate; |
| 633 return DatePrintString(LocalTimeNoCheck(t)) + LocalTimezoneString(t); | 670 var time_zone_string = LocalTimezoneString(t); // May update local offset. |
| 671 return DatePrintString(LocalTimeNoCheck(t)) + time_zone_string; |
| 634 } | 672 } |
| 635 | 673 |
| 636 | 674 |
| 637 // ECMA 262 - 15.9.5.3 | 675 // ECMA 262 - 15.9.5.3 |
| 638 function DateToDateString() { | 676 function DateToDateString() { |
| 639 var t = DATE_VALUE(this); | 677 var t = DATE_VALUE(this); |
| 640 if (NUMBER_IS_NAN(t)) return kInvalidDate; | 678 if (NUMBER_IS_NAN(t)) return kInvalidDate; |
| 641 return DateString(LocalTimeNoCheck(t)); | 679 return DateString(LocalTimeNoCheck(t)); |
| 642 } | 680 } |
| 643 | 681 |
| 644 | 682 |
| 645 // ECMA 262 - 15.9.5.4 | 683 // ECMA 262 - 15.9.5.4 |
| 646 function DateToTimeString() { | 684 function DateToTimeString() { |
| 647 var t = DATE_VALUE(this); | 685 var t = DATE_VALUE(this); |
| 648 if (NUMBER_IS_NAN(t)) return kInvalidDate; | 686 if (NUMBER_IS_NAN(t)) return kInvalidDate; |
| 649 var lt = LocalTimeNoCheck(t); | 687 var time_zone_string = LocalTimezoneString(t); // May update local offset. |
| 650 return TimeString(lt) + LocalTimezoneString(lt); | 688 return TimeString(LocalTimeNoCheck(t)) + time_zone_string; |
| 651 } | 689 } |
| 652 | 690 |
| 653 | 691 |
| 654 // ECMA 262 - 15.9.5.5 | 692 // ECMA 262 - 15.9.5.5 |
| 655 function DateToLocaleString() { | 693 function DateToLocaleString() { |
| 656 return DateToString.call(this); | 694 return DateToString.call(this); |
| 657 } | 695 } |
| 658 | 696 |
| 659 | 697 |
| 660 // ECMA 262 - 15.9.5.6 | 698 // ECMA 262 - 15.9.5.6 |
| (...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1080 "toGMTString", DateToGMTString, | 1118 "toGMTString", DateToGMTString, |
| 1081 "toUTCString", DateToUTCString, | 1119 "toUTCString", DateToUTCString, |
| 1082 "getYear", DateGetYear, | 1120 "getYear", DateGetYear, |
| 1083 "setYear", DateSetYear, | 1121 "setYear", DateSetYear, |
| 1084 "toISOString", DateToISOString, | 1122 "toISOString", DateToISOString, |
| 1085 "toJSON", DateToJSON | 1123 "toJSON", DateToJSON |
| 1086 )); | 1124 )); |
| 1087 } | 1125 } |
| 1088 | 1126 |
| 1089 SetupDate(); | 1127 SetupDate(); |
| OLD | NEW |