Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(739)

Side by Side Diff: src/date.js

Issue 1742012: Port of date and timezone fixes from bleeding edge to... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/partial_snapshots/
Patch Set: Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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();
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698