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

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: 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;
141 }
142
143 void _ensureParts() {
144 if (_parts != null) return;
145 _parts = _computeUpperPart(_localDateInUtcMs);
146 }
147
148 /* patch */ int get millisecond {
149 _ensureParts();
150 return _parts[_MILLISECOND_INDEX];
srdjan 2014/04/22 19:55:46 You could write: int get millisecond => _parts[
Anders Johnsen 2014/04/23 05:58:54 Done.
151 }
152
153 /* patch */ int get second {
154 _ensureParts();
155 return _parts[_SECOND_INDEX];
156 }
157
158 /* patch */ int get minute {
159 _ensureParts();
160 return _parts[_MINUTE_INDEX];
161 }
162
163 /* patch */ int get hour {
164 _ensureParts();
165 return _parts[_HOUR_INDEX];
166 }
167
168 /* patch */ int get day {
169 _ensureParts();
170 return _parts[_DAY_INDEX];
171 }
172
173 /* patch */ int get weekday {
174 _ensureParts();
175 return _parts[_WEEKDAY_INDEX];
176 }
177
178 /* patch */ int get month {
179 _ensureParts();
180 return _parts[_MONTH_INDEX];
181 }
182
183 /* patch */ int get year {
184 _ensureParts();
185 return _parts[_YEAR_INDEX];
150 } 186 }
151 187
152 /** 188 /**
153 * Returns the amount of milliseconds in UTC that represent the same values 189 * Returns the amount of milliseconds in UTC that represent the same values
154 * as [this]. 190 * as [this].
155 * 191 *
156 * Say [:t:] is the result of this function, then 192 * Say [:t:] is the result of this function, then
157 * * [:this.year == new DateTime.fromMillisecondsSinceEpoch(t, true).year:], 193 * * [:this.year == new DateTime.fromMillisecondsSinceEpoch(t, true).year:],
158 * * [:this.month == new DateTime.fromMillisecondsSinceEpoch(t, true).month:], 194 * * [:this.month == new DateTime.fromMillisecondsSinceEpoch(t, true).month:],
159 * * [:this.day == new DateTime.fromMillisecondsSinceEpoch(t, true).day:], 195 * * [:this.day == new DateTime.fromMillisecondsSinceEpoch(t, true).day:],
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 final int DAYS_IN_4_YEARS = 4 * 365 + 1; 313 final int DAYS_IN_4_YEARS = 4 * 365 + 1;
278 final int DAYS_IN_100_YEARS = 25 * DAYS_IN_4_YEARS - 1; 314 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; 315 final int DAYS_YEAR_2098 = DAYS_IN_100_YEARS + 6 * DAYS_IN_4_YEARS;
280 316
281 int days = secondsSinceEpoch ~/ Duration.SECONDS_PER_DAY; 317 int days = secondsSinceEpoch ~/ Duration.SECONDS_PER_DAY;
282 if (days > 0 && days < DAYS_YEAR_2098) { 318 if (days > 0 && days < DAYS_YEAR_2098) {
283 // According to V8 this fast case works for dates from 1970 to 2099. 319 // According to V8 this fast case works for dates from 1970 to 2099.
284 return 1970 + (4 * days + 2) ~/ DAYS_IN_4_YEARS; 320 return 1970 + (4 * days + 2) ~/ DAYS_IN_4_YEARS;
285 } 321 }
286 int ms = secondsSinceEpoch * Duration.MILLISECONDS_PER_SECOND; 322 int ms = secondsSinceEpoch * Duration.MILLISECONDS_PER_SECOND;
287 return _decomposeIntoYearMonthDay(ms)[0]; 323 return _computeUpperPart(ms)[_YEAR_INDEX];
288 } 324 }
289 325
290 /** 326 /**
291 * Returns a date in seconds that is equivalent to the current date. An 327 * 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 328 * equivalent date has the same fields ([:month:], [:day:], etc.) as the
293 * [this], but the [:year:] is in the range [1970..2037]. 329 * [this], but the [:year:] is in the range [1970..2037].
294 * 330 *
295 * * The time since the beginning of the year is the same. 331 * * 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 332 * * If [this] is in a leap year then the returned seconds are in a leap
297 * year, too. 333 * year, too.
(...skipping 19 matching lines...) Expand all
317 static int _timeZoneOffsetInSeconds(int millisecondsSinceEpoch) { 353 static int _timeZoneOffsetInSeconds(int millisecondsSinceEpoch) {
318 int equivalentSeconds = _equivalentSeconds(millisecondsSinceEpoch); 354 int equivalentSeconds = _equivalentSeconds(millisecondsSinceEpoch);
319 return _timeZoneOffsetInSecondsForClampedSeconds(equivalentSeconds); 355 return _timeZoneOffsetInSecondsForClampedSeconds(equivalentSeconds);
320 } 356 }
321 357
322 static String _timeZoneName(int millisecondsSinceEpoch) { 358 static String _timeZoneName(int millisecondsSinceEpoch) {
323 int equivalentSeconds = _equivalentSeconds(millisecondsSinceEpoch); 359 int equivalentSeconds = _equivalentSeconds(millisecondsSinceEpoch);
324 return _timeZoneNameForClampedSeconds(equivalentSeconds); 360 return _timeZoneNameForClampedSeconds(equivalentSeconds);
325 } 361 }
326 } 362 }
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