Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |