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 _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 Loading... | |
| 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 } |
| OLD | NEW |