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

Side by Side Diff: runtime/lib/date_patch.dart

Issue 247373004: Speed up DateTime members, by caching the results. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Cleanup. Created 6 years, 8 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 (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 // Dart core library. 4 // Dart core library.
5 5
6 // VM implementation of DateTime. 6 // VM implementation of DateTime.
7 patch class DateTime { 7 patch class DateTime {
8 // Natives. 8 // Natives.
9 // The natives have been moved up here to work around Issue 10401. 9 // The natives have been moved up here to work around Issue 10401.
10 static int _getCurrentMs() native "DateNatives_currentTimeMillis"; 10 static int _getCurrentMs() native "DateNatives_currentTimeMillis";
11 11
12 static String _timeZoneNameForClampedSeconds(int secondsSinceEpoch) 12 static String _timeZoneNameForClampedSeconds(int secondsSinceEpoch)
13 native "DateNatives_timeZoneName"; 13 native "DateNatives_timeZoneName";
14 14
15 static int _timeZoneOffsetInSecondsForClampedSeconds(int secondsSinceEpoch) 15 static int _timeZoneOffsetInSecondsForClampedSeconds(int secondsSinceEpoch)
16 native "DateNatives_timeZoneOffsetInSeconds"; 16 native "DateNatives_timeZoneOffsetInSeconds";
17 17
18 static int _localTimeZoneAdjustmentInSeconds() 18 static int _localTimeZoneAdjustmentInSeconds()
19 native "DateNatives_localTimeZoneAdjustmentInSeconds"; 19 native "DateNatives_localTimeZoneAdjustmentInSeconds";
20 20
21 static const _MILLISECOND_INDEX = 0;
22 static const _SECOND_INDEX = 1;
23 static const _MINUTE_INDEX = 2;
24 static const _HOUR_INDEX = 3;
25 static const _DAY_INDEX = 4;
26 static const _WEEKDAY_INDEX = 5;
27 static const _MONTH_INDEX = 6;
28 static const _YEAR_INDEX = 7;
29
30 List __parts;
31
21 /* patch */ DateTime._internal(int year, 32 /* patch */ DateTime._internal(int year,
22 int month, 33 int month,
23 int day, 34 int day,
24 int hour, 35 int hour,
25 int minute, 36 int minute,
26 int second, 37 int second,
27 int millisecond, 38 int millisecond,
28 bool isUtc) 39 bool isUtc)
29 : this.isUtc = isUtc, 40 : this.isUtc = isUtc,
30 this.millisecondsSinceEpoch = _brokenDownDateToMillisecondsSinceEpoch( 41 this.millisecondsSinceEpoch = _brokenDownDateToMillisecondsSinceEpoch(
(...skipping 11 matching lines...) Expand all
42 if (isUtc) return "UTC"; 53 if (isUtc) return "UTC";
43 return _timeZoneName(millisecondsSinceEpoch); 54 return _timeZoneName(millisecondsSinceEpoch);
44 } 55 }
45 56
46 /* patch */ Duration get timeZoneOffset { 57 /* patch */ Duration get timeZoneOffset {
47 if (isUtc) return new Duration(); 58 if (isUtc) return new Duration();
48 int offsetInSeconds = _timeZoneOffsetInSeconds(millisecondsSinceEpoch); 59 int offsetInSeconds = _timeZoneOffsetInSeconds(millisecondsSinceEpoch);
49 return new Duration(seconds: offsetInSeconds); 60 return new Duration(seconds: offsetInSeconds);
50 } 61 }
51 62
52 /* patch */ int get year => _decomposeIntoYearMonthDay(_localDateInUtcMs)[0];
53
54 /* patch */ int get month => _decomposeIntoYearMonthDay(_localDateInUtcMs)[1];
55
56 /* patch */ int get day => _decomposeIntoYearMonthDay(_localDateInUtcMs)[2];
57
58 /* patch */ int get hour {
59 int valueInHours = _flooredDivision(_localDateInUtcMs,
60 Duration.MILLISECONDS_PER_HOUR);
61 return valueInHours % Duration.HOURS_PER_DAY;
62 }
63
64 /* patch */ int get minute {
65 int valueInMinutes = _flooredDivision(_localDateInUtcMs,
66 Duration.MILLISECONDS_PER_MINUTE);
67 return valueInMinutes % Duration.MINUTES_PER_HOUR;
68 }
69
70 /* patch */ int get second {
71 // Seconds are unaffected by the timezone the user is in. So we can
72 // directly use the millisecondsSinceEpoch and not [_localDateInUtcMs].
73 int valueInSeconds =
74 _flooredDivision(millisecondsSinceEpoch,
75 Duration.MILLISECONDS_PER_SECOND);
76 return valueInSeconds % Duration.SECONDS_PER_MINUTE;
77 }
78
79 /* patch */ int get millisecond {
80 // Milliseconds are unaffected by the timezone the user is in. So we can
81 // directly use the value and not the [_localDateInUtcValue].
82 return millisecondsSinceEpoch % Duration.MILLISECONDS_PER_SECOND;
83 }
84
85 /** Returns the weekday of [this]. In accordance with ISO 8601 a week
86 * starts with Monday. Monday has the value 1 up to Sunday with 7. */
87 /* patch */ int get weekday {
88 int daysSince1970 =
89 _flooredDivision(_localDateInUtcMs, Duration.MILLISECONDS_PER_DAY);
90 // 1970-1-1 was a Thursday.
91 return ((daysSince1970 + DateTime.THURSDAY - DateTime.MONDAY)
92 % DateTime.DAYS_PER_WEEK) +
93 DateTime.MONDAY;
94 }
95
96
97 /** The first list contains the days until each month in non-leap years. The 63 /** The first list contains the days until each month in non-leap years. The
98 * second list contains the days in leap years. */ 64 * second list contains the days in leap years. */
99 static const List<List<int>> _DAYS_UNTIL_MONTH = 65 static const List<List<int>> _DAYS_UNTIL_MONTH =
100 const [const [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334], 66 const [const [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334],
101 const [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335]]; 67 const [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335]];
102 68
103 // Returns the UTC year, month and day for the corresponding 69 static List _computeUpperPart(int localMs) {
104 // [millisecondsSinceEpoch].
105 // Code is adapted from V8.
106 static List<int> _decomposeIntoYearMonthDay(int millisecondsSinceEpoch) {
107 // TODO(floitsch): cache result.
108 final int DAYS_IN_4_YEARS = 4 * 365 + 1; 70 final int DAYS_IN_4_YEARS = 4 * 365 + 1;
109 final int DAYS_IN_100_YEARS = 25 * DAYS_IN_4_YEARS - 1; 71 final int DAYS_IN_100_YEARS = 25 * DAYS_IN_4_YEARS - 1;
110 final int DAYS_IN_400_YEARS = 4 * DAYS_IN_100_YEARS + 1; 72 final int DAYS_IN_400_YEARS = 4 * DAYS_IN_100_YEARS + 1;
111 final int DAYS_1970_TO_2000 = 30 * 365 + 7; 73 final int DAYS_1970_TO_2000 = 30 * 365 + 7;
112 final int DAYS_OFFSET = 1000 * DAYS_IN_400_YEARS + 5 * DAYS_IN_400_YEARS - 74 final int DAYS_OFFSET = 1000 * DAYS_IN_400_YEARS + 5 * DAYS_IN_400_YEARS -
113 DAYS_1970_TO_2000; 75 DAYS_1970_TO_2000;
114 final int YEARS_OFFSET = 400000; 76 final int YEARS_OFFSET = 400000;
115 77
116 int resultYear = 0; 78 int resultYear = 0;
117 int resultMonth = 0; 79 int resultMonth = 0;
118 int resultDay = 0; 80 int resultDay = 0;
119 81
120 // Always round down. 82 // Always round down.
121 int days = _flooredDivision(millisecondsSinceEpoch, 83 final int daysSince1970 = _flooredDivision(localMs,
122 Duration.MILLISECONDS_PER_DAY); 84 Duration.MILLISECONDS_PER_DAY);
85 int days = daysSince1970;
123 days += DAYS_OFFSET; 86 days += DAYS_OFFSET;
124 resultYear = 400 * (days ~/ DAYS_IN_400_YEARS) - YEARS_OFFSET; 87 resultYear = 400 * (days ~/ DAYS_IN_400_YEARS) - YEARS_OFFSET;
125 days = days.remainder(DAYS_IN_400_YEARS); 88 days = days.remainder(DAYS_IN_400_YEARS);
126 days--; 89 days--;
127 int yd1 = days ~/ DAYS_IN_100_YEARS; 90 int yd1 = days ~/ DAYS_IN_100_YEARS;
128 days = days.remainder(DAYS_IN_100_YEARS); 91 days = days.remainder(DAYS_IN_100_YEARS);
129 resultYear += 100 * yd1; 92 resultYear += 100 * yd1;
130 days++; 93 days++;
131 int yd2 = days ~/ DAYS_IN_4_YEARS; 94 int yd2 = days ~/ DAYS_IN_4_YEARS;
132 days = days.remainder(DAYS_IN_4_YEARS); 95 days = days.remainder(DAYS_IN_4_YEARS);
133 resultYear += 4 * yd2; 96 resultYear += 4 * yd2;
134 days--; 97 days--;
135 int yd3 = days ~/ 365; 98 int yd3 = days ~/ 365;
136 days = days.remainder(365); 99 days = days.remainder(365);
137 resultYear += yd3; 100 resultYear += yd3;
138 101
139 bool isLeap = (yd1 == 0 || yd2 != 0) && yd3 == 0; 102 bool isLeap = (yd1 == 0 || yd2 != 0) && yd3 == 0;
140 if (isLeap) days++; 103 if (isLeap) days++;
141 104
142 List<int> daysUntilMonth = _DAYS_UNTIL_MONTH[isLeap ? 1 : 0]; 105 List<int> daysUntilMonth = _DAYS_UNTIL_MONTH[isLeap ? 1 : 0];
143 for (resultMonth = 12; 106 for (resultMonth = 12;
144 daysUntilMonth[resultMonth - 1] > days; 107 daysUntilMonth[resultMonth - 1] > days;
145 resultMonth--) { 108 resultMonth--) {
146 // Do nothing. 109 // Do nothing.
147 } 110 }
148 resultDay = days - daysUntilMonth[resultMonth - 1] + 1; 111 resultDay = days - daysUntilMonth[resultMonth - 1] + 1;
149 return <int>[resultYear, resultMonth, resultDay]; 112
113 int resultMillisecond = localMs % Duration.MILLISECONDS_PER_SECOND;
114 int resultSecond =
115 _flooredDivision(localMs, Duration.MILLISECONDS_PER_SECOND) %
116 Duration.SECONDS_PER_MINUTE;
117
118 int resultMinute = _flooredDivision(localMs,
119 Duration.MILLISECONDS_PER_MINUTE);
120 resultMinute %= Duration.MINUTES_PER_HOUR;
121
122 int resultHour = _flooredDivision(localMs, Duration.MILLISECONDS_PER_HOUR);
123 resultHour %= Duration.HOURS_PER_DAY;
124
125 // In accordance with ISO 8601 a week
126 // starts with Monday. Monday has the value 1 up to Sunday with 7.
127 // 1970-1-1 was a Thursday.
128 int resultWeekday = ((daysSince1970 + DateTime.THURSDAY - DateTime.MONDAY) %
129 DateTime.DAYS_PER_WEEK) + DateTime.MONDAY;
130
131 List list = new List(_YEAR_INDEX + 1);
132 list[_MILLISECOND_INDEX] = resultMillisecond;
133 list[_SECOND_INDEX] = resultSecond;
134 list[_MINUTE_INDEX] = resultMinute;
135 list[_HOUR_INDEX] = resultHour;
136 list[_DAY_INDEX] = resultDay;
137 list[_WEEKDAY_INDEX] = resultWeekday;
138 list[_MONTH_INDEX] = resultMonth;
139 list[_YEAR_INDEX] = resultYear;
140 return list;
150 } 141 }
151 142
143 get _parts {
144 if (__parts == null) {
145 __parts = _computeUpperPart(_localDateInUtcMs);
146 }
147 return __parts;
148 }
149
150 /* patch */ int get millisecond => _parts[_MILLISECOND_INDEX];
151
152 /* patch */ int get second => _parts[_SECOND_INDEX];
153
154 /* patch */ int get minute => _parts[_MINUTE_INDEX];
155
156 /* patch */ int get hour => _parts[_HOUR_INDEX];
157
158 /* patch */ int get day => _parts[_DAY_INDEX];
159
160 /* patch */ int get weekday => _parts[_WEEKDAY_INDEX];
161
162 /* patch */ int get month => _parts[_MONTH_INDEX];
163
164 /* patch */ int get year => _parts[_YEAR_INDEX];
165
152 /** 166 /**
153 * Returns the amount of milliseconds in UTC that represent the same values 167 * Returns the amount of milliseconds in UTC that represent the same values
154 * as [this]. 168 * as [this].
155 * 169 *
156 * Say [:t:] is the result of this function, then 170 * Say [:t:] is the result of this function, then
157 * * [:this.year == new DateTime.fromMillisecondsSinceEpoch(t, true).year:], 171 * * [:this.year == new DateTime.fromMillisecondsSinceEpoch(t, true).year:],
158 * * [:this.month == new DateTime.fromMillisecondsSinceEpoch(t, true).month:], 172 * * [:this.month == new DateTime.fromMillisecondsSinceEpoch(t, true).month:],
159 * * [:this.day == new DateTime.fromMillisecondsSinceEpoch(t, true).day:], 173 * * [:this.day == new DateTime.fromMillisecondsSinceEpoch(t, true).day:],
160 * * [:this.hour == new DateTime.fromMillisecondsSinceEpoch(t, true).hour:], 174 * * [:this.hour == new DateTime.fromMillisecondsSinceEpoch(t, true).hour:],
161 * * ... 175 * * ...
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 final int DAYS_IN_4_YEARS = 4 * 365 + 1; 291 final int DAYS_IN_4_YEARS = 4 * 365 + 1;
278 final int DAYS_IN_100_YEARS = 25 * DAYS_IN_4_YEARS - 1; 292 final int DAYS_IN_100_YEARS = 25 * DAYS_IN_4_YEARS - 1;
279 final int DAYS_YEAR_2098 = DAYS_IN_100_YEARS + 6 * DAYS_IN_4_YEARS; 293 final int DAYS_YEAR_2098 = DAYS_IN_100_YEARS + 6 * DAYS_IN_4_YEARS;
280 294
281 int days = secondsSinceEpoch ~/ Duration.SECONDS_PER_DAY; 295 int days = secondsSinceEpoch ~/ Duration.SECONDS_PER_DAY;
282 if (days > 0 && days < DAYS_YEAR_2098) { 296 if (days > 0 && days < DAYS_YEAR_2098) {
283 // According to V8 this fast case works for dates from 1970 to 2099. 297 // According to V8 this fast case works for dates from 1970 to 2099.
284 return 1970 + (4 * days + 2) ~/ DAYS_IN_4_YEARS; 298 return 1970 + (4 * days + 2) ~/ DAYS_IN_4_YEARS;
285 } 299 }
286 int ms = secondsSinceEpoch * Duration.MILLISECONDS_PER_SECOND; 300 int ms = secondsSinceEpoch * Duration.MILLISECONDS_PER_SECOND;
287 return _decomposeIntoYearMonthDay(ms)[0]; 301 return _computeUpperPart(ms)[_YEAR_INDEX];
288 } 302 }
289 303
290 /** 304 /**
291 * Returns a date in seconds that is equivalent to the current date. An 305 * Returns a date in seconds that is equivalent to the current date. An
292 * equivalent date has the same fields ([:month:], [:day:], etc.) as the 306 * equivalent date has the same fields ([:month:], [:day:], etc.) as the
293 * [this], but the [:year:] is in the range [1970..2037]. 307 * [this], but the [:year:] is in the range [1970..2037].
294 * 308 *
295 * * The time since the beginning of the year is the same. 309 * * The time since the beginning of the year is the same.
296 * * If [this] is in a leap year then the returned seconds are in a leap 310 * * If [this] is in a leap year then the returned seconds are in a leap
297 * year, too. 311 * year, too.
(...skipping 19 matching lines...) Expand all
317 static int _timeZoneOffsetInSeconds(int millisecondsSinceEpoch) { 331 static int _timeZoneOffsetInSeconds(int millisecondsSinceEpoch) {
318 int equivalentSeconds = _equivalentSeconds(millisecondsSinceEpoch); 332 int equivalentSeconds = _equivalentSeconds(millisecondsSinceEpoch);
319 return _timeZoneOffsetInSecondsForClampedSeconds(equivalentSeconds); 333 return _timeZoneOffsetInSecondsForClampedSeconds(equivalentSeconds);
320 } 334 }
321 335
322 static String _timeZoneName(int millisecondsSinceEpoch) { 336 static String _timeZoneName(int millisecondsSinceEpoch) {
323 int equivalentSeconds = _equivalentSeconds(millisecondsSinceEpoch); 337 int equivalentSeconds = _equivalentSeconds(millisecondsSinceEpoch);
324 return _timeZoneNameForClampedSeconds(equivalentSeconds); 338 return _timeZoneNameForClampedSeconds(equivalentSeconds);
325 } 339 }
326 } 340 }
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