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 | 4 |
| 5 // Mocks of classes and interfaces that Leg cannot read directly. | 5 // Mocks of classes and interfaces that Leg cannot read directly. |
| 6 | 6 |
| 7 // TODO(ahe): Remove this file. | 7 // TODO(ahe): Remove this file. |
| 8 | 8 |
| 9 class JSSyntaxRegExp implements RegExp { | 9 class JSSyntaxRegExp implements RegExp { |
| 10 JSSyntaxRegExp(String pattern, | 10 JSSyntaxRegExp(String pattern, |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 74 | 74 |
| 75 bool operator ==(Object other) { | 75 bool operator ==(Object other) { |
| 76 if (!(other is TimeZoneImplementation)) return false; | 76 if (!(other is TimeZoneImplementation)) return false; |
| 77 return isUtc == other.isUtc; | 77 return isUtc == other.isUtc; |
| 78 } | 78 } |
| 79 | 79 |
| 80 final bool isUtc; | 80 final bool isUtc; |
| 81 } | 81 } |
| 82 | 82 |
| 83 class DateImplementation implements Date { | 83 class DateImplementation implements Date { |
| 84 final int value; | |
| 85 final TimeZoneImplementation timeZone; | |
| 86 | |
| 84 factory DateImplementation(int years, | 87 factory DateImplementation(int years, |
| 85 int month, | 88 int month, |
| 86 int day, | 89 int day, |
| 87 int hours, | 90 int hours, |
| 88 int minutes, | 91 int minutes, |
| 89 int seconds, | 92 int seconds, |
| 90 int milliseconds) { | 93 int milliseconds) { |
| 91 return new DateImplementation.withTimeZone( | 94 return new DateImplementation.withTimeZone( |
| 92 years, month, day, | 95 years, month, day, |
| 93 hours, minutes, seconds, milliseconds, | 96 hours, minutes, seconds, milliseconds, |
| 94 new TimeZoneImplementation.local()); | 97 new TimeZoneImplementation.local()); |
| 95 } | 98 } |
| 96 | 99 |
| 97 DateImplementation.withTimeZone(int years, | 100 DateImplementation.withTimeZone(int years, |
| 98 int month, | 101 int month, |
| 99 int day, | 102 int day, |
| 100 int hours, | 103 int hours, |
| 101 int minutes, | 104 int minutes, |
| 102 int seconds, | 105 int seconds, |
| 103 int milliseconds, | 106 int milliseconds, |
| 104 TimeZoneImplementation timeZone) | 107 TimeZoneImplementation timeZone) |
| 105 : timeZone = timeZone, | 108 : this.timeZone = checkNull(timeZone), |
| 106 value = brokenDownDateToMillisecondsSinceEpoch_( | 109 value = Primitives.valueFromDecomposedDate(years, month, day, |
| 107 years, month, day, hours, minutes, seconds, milliseconds, | 110 hours, minutes, seconds, |
| 108 timeZone.isUtc); | 111 milliseconds, |
| 112 timeZone.isUtc) { | |
| 113 _asJs(); | |
| 114 } | |
| 109 | 115 |
| 110 DateImplementation.now() | 116 DateImplementation.now() |
| 111 : timeZone = new TimeZone.local(), | 117 : timeZone = new TimeZone.local(), |
| 112 value = Primitives.getCurrentMs(); | 118 value = Primitives.dateNow() { |
| 113 | 119 _asJs(); |
| 114 factory DateImplementation.fromString(String formattedString) { | |
| 115 int substringToNumber(String str, int from, int to) { | |
| 116 int result = 0; | |
| 117 for (int i = from; i < to; i++) { | |
| 118 result = result * 10 + str.charCodeAt(i) - "0".charCodeAt(0); | |
| 119 } | |
| 120 return result; | |
| 121 } | |
| 122 | |
| 123 // TODO(floitsch): improve DateImplementation parsing. | |
| 124 // Parse ISO 8601: "2011-05-14 00:37:18.231Z". | |
| 125 int yearMonthSeparator = formattedString.indexOf("-", 0); | |
| 126 if (yearMonthSeparator < 0) throw "UNIMPLEMENTED"; | |
| 127 int monthDaySeparator = | |
| 128 formattedString.indexOf("-", yearMonthSeparator + 1); | |
| 129 if (monthDaySeparator < 0) throw "UNIMPLEMENTED"; | |
| 130 int dateTimeSeparator = formattedString.indexOf(" ", monthDaySeparator + 1); | |
| 131 if (dateTimeSeparator < 0) throw "UNIMPLEMENTED"; | |
| 132 int hoursMinutesSeparator = | |
| 133 formattedString.indexOf(":", dateTimeSeparator + 1); | |
| 134 if (hoursMinutesSeparator < 0) throw "UNIMPLEMENTED"; | |
| 135 int minutesSecondsSeparator = | |
| 136 formattedString.indexOf(":", hoursMinutesSeparator + 1); | |
| 137 if (minutesSecondsSeparator < 0) throw "UNIMPLEMENTED"; | |
| 138 int secondsMillisecondsSeparator = | |
| 139 formattedString.indexOf(".", minutesSecondsSeparator + 1); | |
| 140 bool isUtc = formattedString.endsWith("Z"); | |
| 141 int end = formattedString.length - (isUtc ? 1 : 0); | |
| 142 if (secondsMillisecondsSeparator < 0) secondsMillisecondsSeparator = end; | |
| 143 | |
| 144 int year = substringToNumber(formattedString, 0, yearMonthSeparator); | |
| 145 int month = substringToNumber(formattedString, | |
| 146 yearMonthSeparator + 1, | |
| 147 monthDaySeparator); | |
| 148 int day = substringToNumber(formattedString, | |
| 149 monthDaySeparator + 1, | |
| 150 dateTimeSeparator); | |
| 151 int hours = substringToNumber(formattedString, | |
| 152 dateTimeSeparator + 1, | |
| 153 hoursMinutesSeparator); | |
| 154 int minutes = substringToNumber(formattedString, | |
| 155 hoursMinutesSeparator + 1, | |
| 156 minutesSecondsSeparator); | |
| 157 int seconds = substringToNumber(formattedString, | |
| 158 minutesSecondsSeparator + 1, | |
| 159 secondsMillisecondsSeparator); | |
| 160 int milliseconds = substringToNumber(formattedString, | |
| 161 secondsMillisecondsSeparator + 1, | |
| 162 end); | |
| 163 TimeZone timeZone = (isUtc ? const TimeZone.utc() : new TimeZone.local()); | |
| 164 return new DateImplementation.withTimeZone( | |
| 165 year, month, day, hours, minutes, seconds, milliseconds, timeZone); | |
| 166 } | 120 } |
| 167 | 121 |
| 168 const DateImplementation.fromEpoch(int this.value, | 122 DateImplementation.fromString(String formattedString) |
| 169 TimeZone this.timeZone); | 123 : timeZone = new TimeZone.local(), |
| 124 value = Primitives.valueFromDateString(formattedString) { | |
| 125 _asJs(); | |
| 126 } | |
| 170 | 127 |
| 171 bool operator ==(Object other) { | 128 const DateImplementation.fromEpoch(this.value, this.timeZone); |
| 129 | |
| 130 bool operator ==(other) { | |
| 172 if (!(other is DateImplementation)) return false; | 131 if (!(other is DateImplementation)) return false; |
| 173 return value == other.value && timeZone == other.timeZone; | 132 return (value == other.value) && (timeZone == other.timeZone); |
| 174 } | 133 } |
| 175 | 134 |
| 176 int compareTo(Date other) { | 135 int compareTo(Date other) { |
| 136 checkNull(other); | |
| 177 return value.compareTo(other.value); | 137 return value.compareTo(other.value); |
| 178 } | 138 } |
| 179 | 139 |
| 180 Date changeTimeZone(TimeZone targetTimeZone) { | 140 Date changeTimeZone(TimeZone targetTimeZone) { |
| 181 if (targetTimeZone === null) { | 141 if (targetTimeZone == null) { |
| 182 targetTimeZone = new TimeZoneImplementation.local(); | 142 targetTimeZone = new TimeZoneImplementation.local(); |
| 183 } | 143 } |
| 184 return new Date.fromEpoch(value, targetTimeZone); | 144 return new Date.fromEpoch(value, targetTimeZone); |
| 185 } | 145 } |
| 186 | 146 |
| 187 int get year() { | 147 int get year() => Primitives.getYear(this); |
| 188 int secondsSinceEpoch = secondsSinceEpoch_; | |
| 189 // According to V8 some library calls have troubles with negative values. | |
| 190 // Therefore clamp to 0 - year 2035 (which is less than the size of 32bit). | |
| 191 if (secondsSinceEpoch >= 0 && secondsSinceEpoch < SECONDS_YEAR_2035_) { | |
| 192 return Primitives.getYear(secondsSinceEpoch, timeZone.isUtc); | |
| 193 } | |
| 194 | 148 |
| 195 // Approximate the result. We don't take timeZone into account. | 149 int get month() => Primitives.getMonth(this); |
| 196 int approximateYear = yearsFromSecondsSinceEpoch_(secondsSinceEpoch); | |
| 197 int equivalentYear = equivalentYear_(approximateYear); | |
| 198 int y = Primitives.getYear(equivalentSeconds_(secondsSinceEpoch_), | |
| 199 timeZone.isUtc); | |
| 200 return approximateYear + (y - equivalentYear); | |
| 201 } | |
| 202 | 150 |
| 203 int get month() => Primitives.getMonth(equivalentSeconds_(secondsSinceEpoch_), | 151 int get day() => Primitives.getDay(this); |
| 204 timeZone.isUtc); | |
| 205 | 152 |
| 206 int get day() => Primitives.getDay(equivalentSeconds_(secondsSinceEpoch_), | 153 int get hours() => Primitives.getHours(this); |
| 207 timeZone.isUtc); | |
| 208 | 154 |
| 209 int get hours() => Primitives.getHours(equivalentSeconds_(secondsSinceEpoch_), | 155 int get minutes() => Primitives.getMinutes(this); |
| 210 timeZone.isUtc); | |
| 211 | 156 |
| 212 int get minutes() => | 157 int get seconds() => Primitives.getSeconds(this); |
| 213 Primitives.getMinutes(equivalentSeconds_(secondsSinceEpoch_), | |
| 214 timeZone.isUtc); | |
| 215 | 158 |
| 216 int get seconds() => | 159 int get milliseconds() => Primitives.getMilliseconds(this); |
| 217 Primitives.getSeconds(equivalentSeconds_(secondsSinceEpoch_), | |
| 218 timeZone.isUtc); | |
| 219 | |
| 220 int get milliseconds() { | |
| 221 return value % Duration.MILLISECONDS_PER_SECOND; | |
| 222 } | |
| 223 | |
| 224 int get secondsSinceEpoch_() { | |
| 225 // Always round down. | |
| 226 if (value < 0) { | |
| 227 return (value + 1) ~/ Duration.MILLISECONDS_PER_SECOND - 1; | |
| 228 } else { | |
| 229 return value ~/ Duration.MILLISECONDS_PER_SECOND; | |
| 230 } | |
| 231 } | |
| 232 | 160 |
| 233 int get weekday() { | 161 int get weekday() { |
| 234 final Date unixTimeStart = | 162 // Adjust by one because JS weeks start on Sunday. |
|
ngeoffray
2012/02/21 12:08:07
I'd prefer moving this adjustment in Primitives. A
| |
| 235 new Date.withTimeZone(1970, 1, 1, 0, 0, 0, 0, timeZone); | 163 var day = Primitives.getWeekday(this); |
| 236 int msSince1970 = this.difference(unixTimeStart).inMilliseconds; | 164 return (day + 6) % 7; |
| 237 // Adjust the milliseconds to avoid problems with summer-time. | |
| 238 if (hours < 2) { | |
| 239 msSince1970 += 2 * Duration.MILLISECONDS_PER_HOUR; | |
| 240 } | |
| 241 // Compute the floor of msSince1970 / Duration.MS_PER_DAY. | |
| 242 int daysSince1970; | |
| 243 if (msSince1970 >= 0) { | |
| 244 daysSince1970 = msSince1970 ~/ Duration.MILLISECONDS_PER_DAY; | |
| 245 } else { | |
| 246 daysSince1970 = (msSince1970 - Duration.MILLISECONDS_PER_DAY + 1) ~/ | |
| 247 Duration.MILLISECONDS_PER_DAY; | |
| 248 } | |
| 249 // 1970-1-1 was a Thursday. | |
| 250 return ((daysSince1970 + Date.THU) % Date.DAYS_IN_WEEK); | |
| 251 } | 165 } |
| 252 | 166 |
| 253 bool isLocalTime() { | 167 bool isLocalTime() { |
| 254 return !timeZone.isUtc; | 168 return !timeZone.isUtc; |
| 255 } | 169 } |
| 256 | 170 |
| 257 bool isUtc() { | 171 bool isUtc() { |
| 258 return timeZone.isUtc; | 172 return timeZone.isUtc; |
| 259 } | 173 } |
| 260 | 174 |
| 261 String toString() { | 175 String toString() { |
| 262 String threeDigits(int n) { | |
| 263 if (n >= 100) return "${n}"; | |
| 264 if (n > 10) return "0${n}"; | |
| 265 return "00${n}"; | |
| 266 } | |
| 267 String twoDigits(int n) { | |
| 268 if (n >= 10) return "${n}"; | |
| 269 return "0${n}"; | |
| 270 } | |
| 271 | |
| 272 String m = twoDigits(month); | 176 String m = twoDigits(month); |
| 273 String d = twoDigits(day); | 177 String d = twoDigits(day); |
| 274 String h = twoDigits(hours); | 178 String h = twoDigits(hours); |
| 275 String min = twoDigits(minutes); | 179 String min = twoDigits(minutes); |
| 276 String sec = twoDigits(seconds); | 180 String sec = twoDigits(seconds); |
| 277 String ms = threeDigits(milliseconds); | 181 String ms = threeDigits(milliseconds); |
| 278 if (timeZone.isUtc) { | 182 if (timeZone.isUtc) { |
| 279 return "$year-$m-$d $h:$min:$sec.${ms}Z"; | 183 return "$year-$m-$d $h:$min:$sec.${ms}Z"; |
| 280 } else { | 184 } else { |
| 281 return "$year-$m-$d $h:$min:$sec.$ms"; | 185 return "$year-$m-$d $h:$min:$sec.$ms"; |
| 282 } | 186 } |
| 283 } | 187 } |
| 284 | 188 |
| 285 // Adds the [duration] to this Date instance. | 189 // Adds the [duration] to this Date instance. |
| 286 Date add(Duration duration) { | 190 Date add(Duration duration) { |
| 191 checkNull(duration); | |
| 287 return new DateImplementation.fromEpoch(value + duration.inMilliseconds, | 192 return new DateImplementation.fromEpoch(value + duration.inMilliseconds, |
| 288 timeZone); | 193 timeZone); |
| 289 } | 194 } |
| 290 | 195 |
| 291 // Subtracts the [duration] from this Date instance. | 196 // Subtracts the [duration] from this Date instance. |
| 292 Date subtract(Duration duration) { | 197 Date subtract(Duration duration) { |
| 198 checkNull(duration); | |
| 293 return new DateImplementation.fromEpoch(value - duration.inMilliseconds, | 199 return new DateImplementation.fromEpoch(value - duration.inMilliseconds, |
| 294 timeZone); | 200 timeZone); |
| 295 } | 201 } |
| 296 | 202 |
| 297 // Returns a [Duration] with the difference of [this] and [other]. | 203 // Returns a [Duration] with the difference of [this] and [other]. |
| 298 Duration difference(Date other) { | 204 Duration difference(Date other) { |
| 299 return new DurationImplementation(milliseconds: value - other.value); | 205 checkNull(other); |
| 206 return new Duration(milliseconds: value - other.value); | |
| 300 } | 207 } |
| 301 | 208 |
| 302 final int value; | 209 // Lazily keep a JS Date stored in the dart object. |
| 303 final TimeZoneImplementation timeZone; | 210 var _asJs() => Primitives.lazyAsJsDate(this); |
| 304 | |
| 305 static final int SECONDS_YEAR_2035_ = 2051222400; | |
| 306 | |
| 307 // Returns the UTC year for the corresponding [secondsSinceEpoch]. | |
| 308 // It is relatively fast for values in the range 0 to year 2098. | |
| 309 // Code is adapted from V8. | |
| 310 static int yearsFromSecondsSinceEpoch_(int secondsSinceEpoch) { | |
| 311 final int DAYS_IN_4_YEARS = 4 * 365 + 1; | |
| 312 final int DAYS_IN_100_YEARS = 25 * DAYS_IN_4_YEARS - 1; | |
| 313 final int DAYS_IN_400_YEARS = 4 * DAYS_IN_100_YEARS + 1; | |
| 314 final int DAYS_1970_TO_2000 = 30 * 365 + 7; | |
| 315 final int DAYS_OFFSET = 1000 * DAYS_IN_400_YEARS + 5 * DAYS_IN_400_YEARS - | |
| 316 DAYS_1970_TO_2000; | |
| 317 final int YEARS_OFFSET = 400000; | |
| 318 final int DAYS_YEAR_2098 = DAYS_IN_100_YEARS + 6 * DAYS_IN_4_YEARS; | |
| 319 | |
| 320 int days = secondsSinceEpoch ~/ Duration.SECONDS_PER_DAY; | |
| 321 if (days > 0 && days < DAYS_YEAR_2098) { | |
| 322 // According to V8 this fast case works for dates from 1970 to 2099. | |
| 323 return 1970 + (4 * days + 2) ~/ DAYS_IN_4_YEARS; | |
| 324 } else { | |
| 325 days += DAYS_OFFSET; | |
| 326 int result = 400 * (days ~/ DAYS_IN_400_YEARS) - YEARS_OFFSET; | |
| 327 days = days.remainder(DAYS_IN_400_YEARS); | |
| 328 days--; | |
| 329 int yd1 = days ~/ DAYS_IN_100_YEARS; | |
| 330 days = days.remainder(DAYS_IN_100_YEARS); | |
| 331 result += 100 * yd1; | |
| 332 days++; | |
| 333 int yd2 = days ~/ DAYS_IN_4_YEARS; | |
| 334 days = days.remainder(DAYS_IN_4_YEARS); | |
| 335 result += 4 * yd2; | |
| 336 days--; | |
| 337 int yd3 = days ~/ 365; | |
| 338 days = days.remainder(365); | |
| 339 result += yd3; | |
| 340 return result; | |
| 341 } | |
| 342 } | |
| 343 | |
| 344 // Given [secondsSinceEpoch] returns seconds such that they are at the same | |
| 345 // time in an equivalent year (see [equivalentYear_]). | |
| 346 // Leap seconds are ignored. | |
| 347 static int equivalentSeconds_(int secondsSinceEpoch) { | |
| 348 if (secondsSinceEpoch >= 0 && secondsSinceEpoch < SECONDS_YEAR_2035_) { | |
| 349 return secondsSinceEpoch; | |
| 350 } | |
| 351 int year = yearsFromSecondsSinceEpoch_(secondsSinceEpoch); | |
| 352 int days = dayFromYear_(year); | |
| 353 int equivalentYear = equivalentYear_(year); | |
| 354 int equivalentDays = dayFromYear_(equivalentYear); | |
| 355 int diffDays = equivalentDays - days; | |
| 356 return secondsSinceEpoch + diffDays * Duration.SECONDS_PER_DAY; | |
| 357 } | |
| 358 | |
| 359 // Returns the days since 1970 for the start of the given [year]. | |
| 360 // [year] may be before epoch. | |
| 361 static int dayFromYear_(int year) { | |
| 362 int flooredDivision(int a, int b) { | |
| 363 return (a - (a < 0 ? b - 1 : 0)) ~/ b; | |
| 364 } | |
| 365 | |
| 366 return 365 * (year - 1970) | |
| 367 + flooredDivision(year - 1969, 4) | |
| 368 - flooredDivision(year - 1901, 100) | |
| 369 + flooredDivision(year - 1601, 400); | |
| 370 } | |
| 371 | |
| 372 // Returns a year in the range 2008-2035 matching | |
| 373 // - leap year, and | |
| 374 // - week day of first day. | |
| 375 // Leap seconds are ignored. | |
| 376 // Adapted from V8's date implementation. See ECMA 262 - 15.9.1.9. | |
| 377 static equivalentYear_(int year) { | |
| 378 // Returns 1 if in leap year. 0 otherwise. | |
| 379 bool inLeapYear(year) { | |
| 380 return (year.remainder(4) == 0) && | |
| 381 ((year.remainder(100) != 0) || (year.remainder(400) == 0)); | |
| 382 } | |
| 383 | |
| 384 // Returns the week day (in range 0 - 6). | |
| 385 int weekDay(year) { | |
| 386 // 1/1/1970 was a Thursday. | |
| 387 return (dayFromYear_(year) + 4) % 7; | |
| 388 } | |
| 389 // 1/1/1956 was a Sunday (i.e. weekday 0). 1956 was a leap-year. | |
| 390 // 1/1/1967 was a Sunday (i.e. weekday 0). | |
| 391 // Without leap years a subsequent year has a week day + 1 (for example | |
| 392 // 1/1/1968 was a Monday). With leap-years it jumps over one week day | |
| 393 // (e.g. 1/1/1957 was a Tuesday). | |
| 394 // After 12 years the weekdays have advanced by 12 days + 3 leap days = | |
| 395 // 15 days. 15 % 7 = 1. So after 12 years the week day has always | |
| 396 // (now independently of leap-years) advanced by one. | |
| 397 // weekDay * 12 gives thus a year starting with the wanted weekDay. | |
| 398 int recentYear = (inLeapYear(year) ? 1956 : 1967) + (weekDay(year) * 12); | |
| 399 // Close to the year 2008 the calendar cycles every 4 * 7 years (4 for the | |
| 400 // leap years, 7 for the weekdays). | |
| 401 // Find the year in the range 2008..2037 that is equivalent mod 28. | |
| 402 return 2008 + (recentYear - 2008) % 28; | |
| 403 } | |
| 404 | |
| 405 static brokenDownDateToMillisecondsSinceEpoch_( | |
| 406 int years, int month, int day, | |
| 407 int hours, int minutes, int seconds, int milliseconds, | |
| 408 bool isUtc) { | |
| 409 if ((month < 1) || (month > 12)) { | |
| 410 throw new IllegalArgumentException(); | |
| 411 } | |
| 412 if ((day < 1) || (day > 31)) { | |
| 413 throw new IllegalArgumentException(); | |
| 414 } | |
| 415 // Leap seconds can lead to hours == 24. | |
| 416 if ((hours < 0) || (hours > 24)) { | |
| 417 throw new IllegalArgumentException(); | |
| 418 } | |
| 419 if ((hours == 24) && ((minutes != 0) || (seconds != 0))) { | |
| 420 throw new IllegalArgumentException(); | |
| 421 } | |
| 422 if ((minutes < 0) || (minutes > 59)) { | |
| 423 throw new IllegalArgumentException(); | |
| 424 } | |
| 425 if ((seconds < 0) || (seconds > 59)) { | |
| 426 throw new IllegalArgumentException(); | |
| 427 } | |
| 428 if ((milliseconds < 0) || (milliseconds > 999)) { | |
| 429 throw new IllegalArgumentException(); | |
| 430 } | |
| 431 int equivalentYear; | |
| 432 int offsetInSeconds; | |
| 433 // According to V8 some library calls have troubles with negative values. | |
| 434 // Therefore clamp to 1970 - year 2035 (which is less than the size of | |
| 435 // 32bit). | |
| 436 // We exclude the year 1970 when the time is not UTC, since the epoch | |
| 437 // value could then be negative. | |
| 438 if (years < (isUtc ? 1970 : 1971) || years > 2035) { | |
| 439 equivalentYear = equivalentYear_(years); | |
| 440 int offsetInDays = (dayFromYear_(years) - dayFromYear_(equivalentYear)); | |
| 441 // Leap seconds are ignored. | |
| 442 offsetInSeconds = offsetInDays * Duration.SECONDS_PER_DAY; | |
| 443 } else { | |
| 444 equivalentYear = years; | |
| 445 offsetInSeconds = 0; | |
| 446 } | |
| 447 int secondsSinceEpoch = Primitives.brokenDownDateToSecondsSinceEpoch( | |
| 448 equivalentYear, month, day, hours, minutes, seconds, isUtc); | |
| 449 int adjustedSeconds = secondsSinceEpoch + offsetInSeconds; | |
| 450 return adjustedSeconds * Duration.MILLISECONDS_PER_SECOND + milliseconds; | |
| 451 } | |
| 452 } | 211 } |
| 453 | 212 |
| 454 class ListFactory<E> implements List<E> { | 213 class ListFactory<E> implements List<E> { |
| 455 factory List([int length]) => Primitives.newList(length); | 214 factory List([int length]) => Primitives.newList(length); |
| 456 factory List.from(Iterable<E> other) { | 215 factory List.from(Iterable<E> other) { |
| 457 List<E> result = new List<E>(); | 216 List<E> result = new List<E>(); |
| 458 Iterator<E> iterator = other.iterator(); | 217 Iterator<E> iterator = other.iterator(); |
| 459 while (iterator.hasNext()) { | 218 while (iterator.hasNext()) { |
| 460 result.add(iterator.next()); | 219 result.add(iterator.next()); |
| 461 } | 220 } |
| 462 return result; | 221 return result; |
| 463 } | 222 } |
| 464 } | 223 } |
| 224 | |
| 225 class DurationImplementation implements Duration { | |
| 226 final int inMilliseconds; | |
| 227 | |
| 228 const DurationImplementation([int days = 0, | |
| 229 int hours = 0, | |
| 230 int minutes = 0, | |
| 231 int seconds = 0, | |
| 232 int milliseconds = 0]) | |
| 233 : inMilliseconds = days * Duration.MILLISECONDS_PER_DAY + | |
| 234 hours * Duration.MILLISECONDS_PER_HOUR + | |
| 235 minutes * Duration.MILLISECONDS_PER_MINUTE + | |
| 236 seconds * Duration.MILLISECONDS_PER_SECOND + | |
| 237 milliseconds; | |
| 238 | |
| 239 int get inDays() { | |
| 240 return inMilliseconds ~/ Duration.MILLISECONDS_PER_DAY; | |
| 241 } | |
| 242 | |
| 243 int get inHours() { | |
| 244 return inMilliseconds ~/ Duration.MILLISECONDS_PER_HOUR; | |
| 245 } | |
| 246 | |
| 247 int get inMinutes() { | |
| 248 return inMilliseconds ~/ Duration.MILLISECONDS_PER_MINUTE; | |
| 249 } | |
| 250 | |
| 251 int get inSeconds() { | |
| 252 return inMilliseconds ~/ Duration.MILLISECONDS_PER_SECOND; | |
| 253 } | |
| 254 | |
| 255 bool operator ==(other) { | |
| 256 if (other is !Duration) return false; | |
| 257 return inMilliseconds == other.inMilliseconds; | |
| 258 } | |
| 259 | |
| 260 int hashCode() { | |
| 261 return inMilliseconds.hashCode(); | |
| 262 } | |
| 263 | |
| 264 int compareTo(Duration other) { | |
| 265 return inMilliseconds.compareTo(other.inMilliseconds); | |
| 266 } | |
| 267 | |
| 268 String toString() { | |
| 269 if (inMilliseconds < 0) { | |
| 270 Duration duration = | |
| 271 new DurationImplementation(milliseconds: -inMilliseconds); | |
| 272 return "-${duration}"; | |
| 273 } | |
| 274 String twoDigitMinutes = | |
| 275 twoDigits(inMinutes.remainder(Duration.MINUTES_PER_HOUR)); | |
| 276 String twoDigitSeconds = | |
| 277 twoDigits(inSeconds.remainder(Duration.SECONDS_PER_MINUTE)); | |
| 278 String threeDigitMs = | |
| 279 threeDigits(inMilliseconds.remainder(Duration.MILLISECONDS_PER_SECOND)); | |
| 280 return "${inHours}:${twoDigitMinutes}:${twoDigitSeconds}.${threeDigitMs}"; | |
| 281 } | |
| 282 } | |
| OLD | NEW |