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

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

Issue 1493033003: Add microsecond support to DateTime. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Address comment. Created 5 years 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
« no previous file with comments | « runtime/lib/date.cc ('k') | runtime/vm/bootstrap_natives.h » ('j') | 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 _getCurrentMicros() native "DateTime_currentTimeMicros";
11 11
12 static String _timeZoneNameForClampedSeconds(int secondsSinceEpoch) 12 static String _timeZoneNameForClampedSeconds(int secondsSinceEpoch)
13 native "DateNatives_timeZoneName"; 13 native "DateTime_timeZoneName";
14 14
15 static int _timeZoneOffsetInSecondsForClampedSeconds(int secondsSinceEpoch) 15 static int _timeZoneOffsetInSecondsForClampedSeconds(int secondsSinceEpoch)
16 native "DateNatives_timeZoneOffsetInSeconds"; 16 native "DateTime_timeZoneOffsetInSeconds";
17 17
18 static int _localTimeZoneAdjustmentInSeconds() 18 static int _localTimeZoneAdjustmentInSeconds()
19 native "DateNatives_localTimeZoneAdjustmentInSeconds"; 19 native "DateTime_localTimeZoneAdjustmentInSeconds";
20 20
21 static const _MILLISECOND_INDEX = 0; 21 static const _MICROSECOND_INDEX = 0;
22 static const _SECOND_INDEX = 1; 22 static const _MILLISECOND_INDEX = 1;
23 static const _MINUTE_INDEX = 2; 23 static const _SECOND_INDEX = 2;
24 static const _HOUR_INDEX = 3; 24 static const _MINUTE_INDEX = 3;
25 static const _DAY_INDEX = 4; 25 static const _HOUR_INDEX = 4;
26 static const _WEEKDAY_INDEX = 5; 26 static const _DAY_INDEX = 5;
27 static const _MONTH_INDEX = 6; 27 static const _WEEKDAY_INDEX = 6;
28 static const _YEAR_INDEX = 7; 28 static const _MONTH_INDEX = 7;
29 static const _YEAR_INDEX = 8;
29 30
30 List __parts; 31 List __parts;
31 32
33 /* patch */ DateTime.fromMillisecondsSinceEpoch(int millisecondsSinceEpoch,
34 {bool isUtc: false})
35 : this._withValue(
36 millisecondsSinceEpoch * Duration.MICROSECONDS_PER_MILLISECOND,
37 isUtc: isUtc);
38
39 /* patch */ DateTime.fromMicrosecondsSinceEpoch(int microsecondsSinceEpoch,
40 {bool isUtc: false})
41 : this._withValue(microsecondsSinceEpoch, isUtc: isUtc);
42
32 /* patch */ DateTime._internal(int year, 43 /* patch */ DateTime._internal(int year,
33 int month, 44 int month,
34 int day, 45 int day,
35 int hour, 46 int hour,
36 int minute, 47 int minute,
37 int second, 48 int second,
38 int millisecond, 49 int millisecond,
50 int microsecond,
39 bool isUtc) 51 bool isUtc)
40 : this.isUtc = isUtc, 52 : this.isUtc = isUtc,
41 this.millisecondsSinceEpoch = _brokenDownDateToMillisecondsSinceEpoch( 53 this._value = _brokenDownDateToValue(
42 year, month, day, hour, minute, second, millisecond, isUtc) { 54 year, month, day, hour, minute, second, millisecond, microsecond,
43 if (millisecondsSinceEpoch == null) throw new ArgumentError(); 55 isUtc) {
56 if (_value == null) throw new ArgumentError();
44 if (isUtc == null) throw new ArgumentError(); 57 if (isUtc == null) throw new ArgumentError();
45 } 58 }
46 59
47 /* patch */ DateTime._now() 60 /* patch */ DateTime._now()
48 : isUtc = false, 61 : isUtc = false,
49 millisecondsSinceEpoch = _getCurrentMs() { 62 _value = _getCurrentMicros() {
50 } 63 }
51 64
52 /* patch */ String get timeZoneName { 65 /* patch */ String get timeZoneName {
53 if (isUtc) return "UTC"; 66 if (isUtc) return "UTC";
54 return _timeZoneName(millisecondsSinceEpoch); 67 return _timeZoneName(microsecondsSinceEpoch);
55 } 68 }
56 69
57 /* patch */ Duration get timeZoneOffset { 70 /* patch */ Duration get timeZoneOffset {
58 if (isUtc) return new Duration(); 71 if (isUtc) return new Duration();
59 int offsetInSeconds = _timeZoneOffsetInSeconds(millisecondsSinceEpoch); 72 int offsetInSeconds = _timeZoneOffsetInSeconds(microsecondsSinceEpoch);
60 return new Duration(seconds: offsetInSeconds); 73 return new Duration(seconds: offsetInSeconds);
61 } 74 }
62 75
63 /** The first list contains the days until each month in non-leap years. The 76 /** The first list contains the days until each month in non-leap years. The
64 * second list contains the days in leap years. */ 77 * second list contains the days in leap years. */
65 static const List<List<int>> _DAYS_UNTIL_MONTH = 78 static const List<List<int>> _DAYS_UNTIL_MONTH =
66 const [const [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334], 79 const [const [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334],
67 const [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335]]; 80 const [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335]];
68 81
69 static List _computeUpperPart(int localMs) { 82 static List _computeUpperPart(int localMicros) {
70 const int DAYS_IN_4_YEARS = 4 * 365 + 1; 83 const int DAYS_IN_4_YEARS = 4 * 365 + 1;
71 const int DAYS_IN_100_YEARS = 25 * DAYS_IN_4_YEARS - 1; 84 const int DAYS_IN_100_YEARS = 25 * DAYS_IN_4_YEARS - 1;
72 const int DAYS_IN_400_YEARS = 4 * DAYS_IN_100_YEARS + 1; 85 const int DAYS_IN_400_YEARS = 4 * DAYS_IN_100_YEARS + 1;
73 const int DAYS_1970_TO_2000 = 30 * 365 + 7; 86 const int DAYS_1970_TO_2000 = 30 * 365 + 7;
74 const int DAYS_OFFSET = 1000 * DAYS_IN_400_YEARS + 5 * DAYS_IN_400_YEARS - 87 const int DAYS_OFFSET = 1000 * DAYS_IN_400_YEARS + 5 * DAYS_IN_400_YEARS -
75 DAYS_1970_TO_2000; 88 DAYS_1970_TO_2000;
76 const int YEARS_OFFSET = 400000; 89 const int YEARS_OFFSET = 400000;
77 90
78 int resultYear = 0; 91 int resultYear = 0;
79 int resultMonth = 0; 92 int resultMonth = 0;
80 int resultDay = 0; 93 int resultDay = 0;
81 94
82 // Always round down. 95 // Always round down.
83 final int daysSince1970 = _flooredDivision(localMs, 96 final int daysSince1970 = _flooredDivision(localMicros,
84 Duration.MILLISECONDS_PER_DAY); 97 Duration.MICROSECONDS_PER_DAY);
85 int days = daysSince1970; 98 int days = daysSince1970;
86 days += DAYS_OFFSET; 99 days += DAYS_OFFSET;
87 resultYear = 400 * (days ~/ DAYS_IN_400_YEARS) - YEARS_OFFSET; 100 resultYear = 400 * (days ~/ DAYS_IN_400_YEARS) - YEARS_OFFSET;
88 days = days.remainder(DAYS_IN_400_YEARS); 101 days = days.remainder(DAYS_IN_400_YEARS);
89 days--; 102 days--;
90 int yd1 = days ~/ DAYS_IN_100_YEARS; 103 int yd1 = days ~/ DAYS_IN_100_YEARS;
91 days = days.remainder(DAYS_IN_100_YEARS); 104 days = days.remainder(DAYS_IN_100_YEARS);
92 resultYear += 100 * yd1; 105 resultYear += 100 * yd1;
93 days++; 106 days++;
94 int yd2 = days ~/ DAYS_IN_4_YEARS; 107 int yd2 = days ~/ DAYS_IN_4_YEARS;
95 days = days.remainder(DAYS_IN_4_YEARS); 108 days = days.remainder(DAYS_IN_4_YEARS);
96 resultYear += 4 * yd2; 109 resultYear += 4 * yd2;
97 days--; 110 days--;
98 int yd3 = days ~/ 365; 111 int yd3 = days ~/ 365;
99 days = days.remainder(365); 112 days = days.remainder(365);
100 resultYear += yd3; 113 resultYear += yd3;
101 114
102 bool isLeap = (yd1 == 0 || yd2 != 0) && yd3 == 0; 115 bool isLeap = (yd1 == 0 || yd2 != 0) && yd3 == 0;
103 if (isLeap) days++; 116 if (isLeap) days++;
104 117
105 List<int> daysUntilMonth = _DAYS_UNTIL_MONTH[isLeap ? 1 : 0]; 118 List<int> daysUntilMonth = _DAYS_UNTIL_MONTH[isLeap ? 1 : 0];
106 for (resultMonth = 12; 119 for (resultMonth = 12;
107 daysUntilMonth[resultMonth - 1] > days; 120 daysUntilMonth[resultMonth - 1] > days;
108 resultMonth--) { 121 resultMonth--) {
109 // Do nothing. 122 // Do nothing.
110 } 123 }
111 resultDay = days - daysUntilMonth[resultMonth - 1] + 1; 124 resultDay = days - daysUntilMonth[resultMonth - 1] + 1;
112 125
113 int resultMillisecond = localMs % Duration.MILLISECONDS_PER_SECOND; 126 int resultMicrosecond = localMicros % Duration.MICROSECONDS_PER_MILLISECOND;
127 int resultMillisecond =
128 _flooredDivision(localMicros, Duration.MICROSECONDS_PER_MILLISECOND) %
129 Duration.MILLISECONDS_PER_SECOND;
114 int resultSecond = 130 int resultSecond =
115 _flooredDivision(localMs, Duration.MILLISECONDS_PER_SECOND) % 131 _flooredDivision(localMicros, Duration.MICROSECONDS_PER_SECOND) %
116 Duration.SECONDS_PER_MINUTE; 132 Duration.SECONDS_PER_MINUTE;
117 133
118 int resultMinute = _flooredDivision(localMs, 134 int resultMinute = _flooredDivision(localMicros,
119 Duration.MILLISECONDS_PER_MINUTE); 135 Duration.MICROSECONDS_PER_MINUTE);
120 resultMinute %= Duration.MINUTES_PER_HOUR; 136 resultMinute %= Duration.MINUTES_PER_HOUR;
121 137
122 int resultHour = _flooredDivision(localMs, Duration.MILLISECONDS_PER_HOUR); 138 int resultHour =
139 _flooredDivision(localMicros, Duration.MICROSECONDS_PER_HOUR);
123 resultHour %= Duration.HOURS_PER_DAY; 140 resultHour %= Duration.HOURS_PER_DAY;
124 141
125 // In accordance with ISO 8601 a week 142 // In accordance with ISO 8601 a week
126 // starts with Monday. Monday has the value 1 up to Sunday with 7. 143 // starts with Monday. Monday has the value 1 up to Sunday with 7.
127 // 1970-1-1 was a Thursday. 144 // 1970-1-1 was a Thursday.
128 int resultWeekday = ((daysSince1970 + DateTime.THURSDAY - DateTime.MONDAY) % 145 int resultWeekday = ((daysSince1970 + DateTime.THURSDAY - DateTime.MONDAY) %
129 DateTime.DAYS_PER_WEEK) + DateTime.MONDAY; 146 DateTime.DAYS_PER_WEEK) + DateTime.MONDAY;
130 147
131 List list = new List(_YEAR_INDEX + 1); 148 List list = new List(_YEAR_INDEX + 1);
149 list[_MICROSECOND_INDEX] = resultMicrosecond;
132 list[_MILLISECOND_INDEX] = resultMillisecond; 150 list[_MILLISECOND_INDEX] = resultMillisecond;
133 list[_SECOND_INDEX] = resultSecond; 151 list[_SECOND_INDEX] = resultSecond;
134 list[_MINUTE_INDEX] = resultMinute; 152 list[_MINUTE_INDEX] = resultMinute;
135 list[_HOUR_INDEX] = resultHour; 153 list[_HOUR_INDEX] = resultHour;
136 list[_DAY_INDEX] = resultDay; 154 list[_DAY_INDEX] = resultDay;
137 list[_WEEKDAY_INDEX] = resultWeekday; 155 list[_WEEKDAY_INDEX] = resultWeekday;
138 list[_MONTH_INDEX] = resultMonth; 156 list[_MONTH_INDEX] = resultMonth;
139 list[_YEAR_INDEX] = resultYear; 157 list[_YEAR_INDEX] = resultYear;
140 return list; 158 return list;
141 } 159 }
142 160
143 get _parts { 161 get _parts {
144 if (__parts == null) { 162 if (__parts == null) {
145 __parts = _computeUpperPart(_localDateInUtcMs); 163 __parts = _computeUpperPart(_localDateInUtcMicros);
146 } 164 }
147 return __parts; 165 return __parts;
148 } 166 }
149 167
168 /* patch */ DateTime add(Duration duration) {
169 return new DateTime._withValue(
170 _value + duration.inMicroseconds, isUtc: isUtc);
171 }
172
173 /* patch */ DateTime subtract(Duration duration) {
174 return new DateTime._withValue(
175 _value - duration.inMicroseconds, isUtc: isUtc);
176 }
177
178 /* patch */ Duration difference(DateTime other) {
179 return new Duration(microseconds: _value - other._value);
180 }
181
182 /* patch */ int get millisecondsSinceEpoch =>
183 _value ~/ Duration.MICROSECONDS_PER_MILLISECOND;
184
185 /* patch */ int get microsecondsSinceEpoch => _value;
186
187 /* patch */ int get microsecond => _parts[_MICROSECOND_INDEX];
188
150 /* patch */ int get millisecond => _parts[_MILLISECOND_INDEX]; 189 /* patch */ int get millisecond => _parts[_MILLISECOND_INDEX];
151 190
152 /* patch */ int get second => _parts[_SECOND_INDEX]; 191 /* patch */ int get second => _parts[_SECOND_INDEX];
153 192
154 /* patch */ int get minute => _parts[_MINUTE_INDEX]; 193 /* patch */ int get minute => _parts[_MINUTE_INDEX];
155 194
156 /* patch */ int get hour => _parts[_HOUR_INDEX]; 195 /* patch */ int get hour => _parts[_HOUR_INDEX];
157 196
158 /* patch */ int get day => _parts[_DAY_INDEX]; 197 /* patch */ int get day => _parts[_DAY_INDEX];
159 198
160 /* patch */ int get weekday => _parts[_WEEKDAY_INDEX]; 199 /* patch */ int get weekday => _parts[_WEEKDAY_INDEX];
161 200
162 /* patch */ int get month => _parts[_MONTH_INDEX]; 201 /* patch */ int get month => _parts[_MONTH_INDEX];
163 202
164 /* patch */ int get year => _parts[_YEAR_INDEX]; 203 /* patch */ int get year => _parts[_YEAR_INDEX];
165 204
166 /** 205 /**
167 * Returns the amount of milliseconds in UTC that represent the same values 206 * Returns the amount of microseconds in UTC that represent the same values
168 * as [this]. 207 * as [this].
169 * 208 *
170 * Say [:t:] is the result of this function, then 209 * Say `t` is the result of this function, then
171 * * [:this.year == new DateTime.fromMillisecondsSinceEpoch(t, true).year:], 210 * * `this.year == new DateTime.fromMicrosecondsSinceEpoch(t, true).year`,
172 * * [:this.month == new DateTime.fromMillisecondsSinceEpoch(t, true).month:], 211 * * `this.month == new DateTime.fromMicrosecondsSinceEpoch(t, true).month`,
173 * * [:this.day == new DateTime.fromMillisecondsSinceEpoch(t, true).day:], 212 * * `this.day == new DateTime.fromMicrosecondsSinceEpoch(t, true).day`,
174 * * [:this.hour == new DateTime.fromMillisecondsSinceEpoch(t, true).hour:], 213 * * `this.hour == new DateTime.fromMicrosecondsSinceEpoch(t, true).hour`,
175 * * ... 214 * * ...
176 * 215 *
177 * Daylight savings is computed as if the date was computed in [1970..2037]. 216 * Daylight savings is computed as if the date was computed in [1970..2037].
178 * If [this] lies outside this range then it is a year with similar 217 * If [this] lies outside this range then it is a year with similar
179 * properties (leap year, weekdays) is used instead. 218 * properties (leap year, weekdays) is used instead.
180 */ 219 */
181 int get _localDateInUtcMs { 220 int get _localDateInUtcMicros {
182 int ms = millisecondsSinceEpoch; 221 int micros = _value;
183 if (isUtc) return ms; 222 if (isUtc) return micros;
184 int offset = 223 int offset =
185 _timeZoneOffsetInSeconds(ms) * Duration.MILLISECONDS_PER_SECOND; 224 _timeZoneOffsetInSeconds(micros) * Duration.MICROSECONDS_PER_SECOND;
186 return ms + offset; 225 return micros + offset;
187 } 226 }
188 227
189 static int _flooredDivision(int a, int b) { 228 static int _flooredDivision(int a, int b) {
190 return (a - (a < 0 ? b - 1 : 0)) ~/ b; 229 return (a - (a < 0 ? b - 1 : 0)) ~/ b;
191 } 230 }
192 231
193 // Returns the days since 1970 for the start of the given [year]. 232 // Returns the days since 1970 for the start of the given [year].
194 // [year] may be before epoch. 233 // [year] may be before epoch.
195 static int _dayFromYear(int year) { 234 static int _dayFromYear(int year) {
196 return 365 * (year - 1970) 235 return 365 * (year - 1970)
197 + _flooredDivision(year - 1969, 4) 236 + _flooredDivision(year - 1969, 4)
198 - _flooredDivision(year - 1901, 100) 237 - _flooredDivision(year - 1901, 100)
199 + _flooredDivision(year - 1601, 400); 238 + _flooredDivision(year - 1601, 400);
200 } 239 }
201 240
202 static bool _isLeapYear(y) { 241 static bool _isLeapYear(y) {
203 // (y % 16 == 0) matches multiples of 400, and is faster than % 400. 242 // (y % 16 == 0) matches multiples of 400, and is faster than % 400.
204 return (y % 4 == 0) && ((y % 16 == 0) || (y % 100 != 0)); 243 return (y % 4 == 0) && ((y % 16 == 0) || (y % 100 != 0));
205 } 244 }
206 245
207 /* patch */ static int _brokenDownDateToMillisecondsSinceEpoch( 246 /// Converts the given broken down date to microseconds.
247 /* patch */ static int _brokenDownDateToValue(
208 int year, int month, int day, 248 int year, int month, int day,
209 int hour, int minute, int second, int millisecond, 249 int hour, int minute, int second, int millisecond, int microsecond,
210 bool isUtc) { 250 bool isUtc) {
211 // Simplify calculations by working with zero-based month. 251 // Simplify calculations by working with zero-based month.
212 --month; 252 --month;
213 // Deal with under and overflow. 253 // Deal with under and overflow.
214 if (month >= 12) { 254 if (month >= 12) {
215 year += month ~/ 12; 255 year += month ~/ 12;
216 month = month % 12; 256 month = month % 12;
217 } else if (month < 0) { 257 } else if (month < 0) {
218 int realMonth = month % 12; 258 int realMonth = month % 12;
219 year += (month - realMonth) ~/ 12; 259 year += (month - realMonth) ~/ 12;
220 month = realMonth; 260 month = realMonth;
221 } 261 }
222 262
223 // First compute the seconds in UTC, independent of the [isUtc] flag. If 263 // First compute the seconds in UTC, independent of the [isUtc] flag. If
224 // necessary we will add the time-zone offset later on. 264 // necessary we will add the time-zone offset later on.
225 int days = day - 1; 265 int days = day - 1;
226 days += _DAYS_UNTIL_MONTH[_isLeapYear(year) ? 1 : 0][month]; 266 days += _DAYS_UNTIL_MONTH[_isLeapYear(year) ? 1 : 0][month];
227 days += _dayFromYear(year); 267 days += _dayFromYear(year);
228 int millisecondsSinceEpoch = 268 int microsecondsSinceEpoch =
229 days * Duration.MILLISECONDS_PER_DAY + 269 days * Duration.MICROSECONDS_PER_DAY +
230 hour * Duration.MILLISECONDS_PER_HOUR + 270 hour * Duration.MICROSECONDS_PER_HOUR +
231 minute * Duration.MILLISECONDS_PER_MINUTE + 271 minute * Duration.MICROSECONDS_PER_MINUTE +
232 second * Duration.MILLISECONDS_PER_SECOND + 272 second * Duration.MICROSECONDS_PER_SECOND +
233 millisecond; 273 millisecond * Duration.MICROSECONDS_PER_MILLISECOND +
274 microsecond;
234 275
235 // Since [_timeZoneOffsetInSeconds] will crash if the input is far out of 276 // Since [_timeZoneOffsetInSeconds] will crash if the input is far out of
236 // the valid range we do a preliminary test that weeds out values that can 277 // the valid range we do a preliminary test that weeds out values that can
237 // not become valid even with timezone adjustments. 278 // not become valid even with timezone adjustments.
238 // The timezone adjustment is always less than a day, so adding a security 279 // The timezone adjustment is always less than a day, so adding a security
239 // margin of one day should be enough. 280 // margin of one day should be enough.
240 if (millisecondsSinceEpoch.abs() > 281 if (microsecondsSinceEpoch.abs() >
241 (_MAX_MILLISECONDS_SINCE_EPOCH + Duration.MILLISECONDS_PER_DAY)) { 282 _MAX_MILLISECONDS_SINCE_EPOCH * 1000 + Duration.MICROSECONDS_PER_DAY) {
242 return null; 283 return null;
243 } 284 }
244 285
245 if (!isUtc) { 286 if (!isUtc) {
246 // Note that we need to remove the local timezone adjustement before 287 // Note that we need to remove the local timezone adjustement before
247 // asking for the correct zone offset. 288 // asking for the correct zone offset.
248 int adjustment = _localTimeZoneAdjustmentInSeconds() * 289 int adjustment = _localTimeZoneAdjustmentInSeconds() *
249 Duration.MILLISECONDS_PER_SECOND; 290 Duration.MICROSECONDS_PER_SECOND;
291
250 int zoneOffset = 292 int zoneOffset =
251 _timeZoneOffsetInSeconds(millisecondsSinceEpoch - adjustment); 293 _timeZoneOffsetInSeconds(microsecondsSinceEpoch - adjustment);
252 millisecondsSinceEpoch -= zoneOffset * Duration.MILLISECONDS_PER_SECOND; 294 microsecondsSinceEpoch -= zoneOffset * Duration.MICROSECONDS_PER_SECOND;
253 } 295 }
254 if (millisecondsSinceEpoch.abs() > _MAX_MILLISECONDS_SINCE_EPOCH) { 296 if (microsecondsSinceEpoch.abs() >
297 _MAX_MILLISECONDS_SINCE_EPOCH * Duration.MICROSECONDS_PER_MILLISECOND) {
255 return null; 298 return null;
256 } 299 }
257 return millisecondsSinceEpoch; 300 return microsecondsSinceEpoch;
258 } 301 }
259 302
260 static int _weekDay(y) { 303 static int _weekDay(y) {
261 // 1/1/1970 was a Thursday. 304 // 1/1/1970 was a Thursday.
262 return (_dayFromYear(y) + 4) % 7; 305 return (_dayFromYear(y) + 4) % 7;
263 } 306 }
264 307
265 /** 308 /**
266 * Returns a year in the range 2008-2035 matching 309 * Returns a year in the range 2008-2035 matching
267 * * leap year, and 310 * * leap year, and
(...skipping 29 matching lines...) Expand all
297 static int _yearsFromSecondsSinceEpoch(int secondsSinceEpoch) { 340 static int _yearsFromSecondsSinceEpoch(int secondsSinceEpoch) {
298 const int DAYS_IN_4_YEARS = 4 * 365 + 1; 341 const int DAYS_IN_4_YEARS = 4 * 365 + 1;
299 const int DAYS_IN_100_YEARS = 25 * DAYS_IN_4_YEARS - 1; 342 const int DAYS_IN_100_YEARS = 25 * DAYS_IN_4_YEARS - 1;
300 const int DAYS_YEAR_2098 = DAYS_IN_100_YEARS + 6 * DAYS_IN_4_YEARS; 343 const int DAYS_YEAR_2098 = DAYS_IN_100_YEARS + 6 * DAYS_IN_4_YEARS;
301 344
302 int days = secondsSinceEpoch ~/ Duration.SECONDS_PER_DAY; 345 int days = secondsSinceEpoch ~/ Duration.SECONDS_PER_DAY;
303 if (days > 0 && days < DAYS_YEAR_2098) { 346 if (days > 0 && days < DAYS_YEAR_2098) {
304 // According to V8 this fast case works for dates from 1970 to 2099. 347 // According to V8 this fast case works for dates from 1970 to 2099.
305 return 1970 + (4 * days + 2) ~/ DAYS_IN_4_YEARS; 348 return 1970 + (4 * days + 2) ~/ DAYS_IN_4_YEARS;
306 } 349 }
307 int ms = secondsSinceEpoch * Duration.MILLISECONDS_PER_SECOND; 350 int micros = secondsSinceEpoch * Duration.MICROSECONDS_PER_SECOND;
308 return _computeUpperPart(ms)[_YEAR_INDEX]; 351 return _computeUpperPart(micros)[_YEAR_INDEX];
309 } 352 }
310 353
311 /** 354 /**
312 * Returns a date in seconds that is equivalent to the current date. An 355 * Returns a date in seconds that is equivalent to the current date. An
313 * equivalent date has the same fields ([:month:], [:day:], etc.) as the 356 * equivalent date has the same fields (`month`, `day`, etc.) as the
314 * [this], but the [:year:] is in the range [1970..2037]. 357 * [this], but the `year` is in the range [1970..2037].
315 * 358 *
316 * * The time since the beginning of the year is the same. 359 * * The time since the beginning of the year is the same.
317 * * If [this] is in a leap year then the returned seconds are in a leap 360 * * If [this] is in a leap year then the returned seconds are in a leap
318 * year, too. 361 * year, too.
319 * * The week day of [this] is the same as the one for the returned date. 362 * * The week day of [this] is the same as the one for the returned date.
320 */ 363 */
321 static int _equivalentSeconds(int millisecondsSinceEpoch) { 364 static int _equivalentSeconds(int microsecondsSinceEpoch) {
322 const int CUT_OFF_SECONDS = 2100000000; 365 const int CUT_OFF_SECONDS = 2100000000;
323 366
324 int secondsSinceEpoch = _flooredDivision(millisecondsSinceEpoch, 367 int secondsSinceEpoch = _flooredDivision(microsecondsSinceEpoch,
325 Duration.MILLISECONDS_PER_SECOND); 368 Duration.MICROSECONDS_PER_SECOND);
326 369
327 if (secondsSinceEpoch < 0 || secondsSinceEpoch >= CUT_OFF_SECONDS) { 370 if (secondsSinceEpoch < 0 || secondsSinceEpoch >= CUT_OFF_SECONDS) {
328 int year = _yearsFromSecondsSinceEpoch(secondsSinceEpoch); 371 int year = _yearsFromSecondsSinceEpoch(secondsSinceEpoch);
329 int days = _dayFromYear(year); 372 int days = _dayFromYear(year);
330 int equivalentYear = _equivalentYear(year); 373 int equivalentYear = _equivalentYear(year);
331 int equivalentDays = _dayFromYear(equivalentYear); 374 int equivalentDays = _dayFromYear(equivalentYear);
332 int diffDays = equivalentDays - days; 375 int diffDays = equivalentDays - days;
333 secondsSinceEpoch += diffDays * Duration.SECONDS_PER_DAY; 376 secondsSinceEpoch += diffDays * Duration.SECONDS_PER_DAY;
334 } 377 }
335 return secondsSinceEpoch; 378 return secondsSinceEpoch;
336 } 379 }
337 380
338 static int _timeZoneOffsetInSeconds(int millisecondsSinceEpoch) { 381 static int _timeZoneOffsetInSeconds(int microsecondsSinceEpoch) {
339 int equivalentSeconds = _equivalentSeconds(millisecondsSinceEpoch); 382 int equivalentSeconds = _equivalentSeconds(microsecondsSinceEpoch);
340 return _timeZoneOffsetInSecondsForClampedSeconds(equivalentSeconds); 383 return _timeZoneOffsetInSecondsForClampedSeconds(equivalentSeconds);
341 } 384 }
342 385
343 static String _timeZoneName(int millisecondsSinceEpoch) { 386 static String _timeZoneName(int microsecondsSinceEpoch) {
344 int equivalentSeconds = _equivalentSeconds(millisecondsSinceEpoch); 387 int equivalentSeconds = _equivalentSeconds(microsecondsSinceEpoch);
345 return _timeZoneNameForClampedSeconds(equivalentSeconds); 388 return _timeZoneNameForClampedSeconds(equivalentSeconds);
346 } 389 }
347 } 390 }
OLDNEW
« no previous file with comments | « runtime/lib/date.cc ('k') | runtime/vm/bootstrap_natives.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698