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

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

Powered by Google App Engine
This is Rietveld 408576698