| // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| part of dart.core; |
| |
| /// A span of time, such as 27 days, 4 hours, 12 minutes, and 3 seconds. |
| /// |
| /// A `Duration` represents a difference from one point in time to another. The |
| /// duration may be "negative" if the difference is from a later time to an |
| /// earlier. |
| /// |
| /// Durations are context independent. For example, a duration of 2 days is |
| /// always 48 hours, even when it is added to a `DateTime` just when the |
| /// time zone is about to do a daylight-savings switch. (See [DateTime.add]). |
| /// |
| /// Despite the same name, a `Duration` object does not implement "Durations" |
| /// as specified by ISO 8601. In particular, a duration object does not keep |
| /// track of the individually provided members (such as "days" or "hours"), but |
| /// only uses these arguments to compute the length of the corresponding time |
| /// interval. |
| /// |
| /// To create a new Duration object, use this class's single constructor |
| /// giving the appropriate arguments: |
| /// ```dart |
| /// var fastestMarathon = const Duration(hours: 2, minutes: 3, seconds: 2); |
| /// ``` |
| /// The [Duration] is the sum of all individual parts. |
| /// This means that individual parts can be larger than the next-bigger unit. |
| /// For example, [inMinutes] can be greater than 59. |
| /// ```dart |
| /// const fastestMarathon = const Duration(hours: 2, minutes: 3, seconds: 2); |
| /// assert(fastestMarathon.inMinutes == 123); |
| /// ``` |
| /// All individual parts are allowed to be negative. |
| /// |
| /// Use one of the properties, such as [inDays], |
| /// to retrieve the integer value of the Duration in the specified time unit. |
| /// Note that the returned value is rounded down. |
| /// For example, |
| /// ```dart |
| /// var aLongWeekend = const Duration(hours: 88); |
| /// assert(aLongWeekend.inDays == 3); |
| /// ``` |
| /// This class provides a collection of arithmetic |
| /// and comparison operators, |
| /// plus a set of constants useful for converting time units. |
| /// |
| /// See [DateTime] to represent a point in time. |
| /// See [Stopwatch] to measure time-spans. |
| class Duration implements Comparable<Duration> { |
| /// The number of microseconds per millisecond. |
| static const int microsecondsPerMillisecond = 1000; |
| |
| /// The number of milliseconds per second. |
| static const int millisecondsPerSecond = 1000; |
| |
| /// The number of seconds per minute. |
| /// |
| /// Notice that some minutes of official clock time might |
| /// differ in length because of leap seconds. |
| /// The [Duration] and [DateTime] classes ignore leap seconds |
| /// and consider all minutes to have 60 seconds. |
| static const int secondsPerMinute = 60; |
| |
| /// The number of minutes per hour. |
| static const int minutesPerHour = 60; |
| |
| /// The number of hours per day. |
| /// |
| /// Notice that some days may differ in length because |
| /// of time zone changes due to daylight saving. |
| /// The [Duration] class is time zone agnostic and |
| /// considers all days to have 24 hours. |
| static const int hoursPerDay = 24; |
| |
| /// The number of microseconds per second. |
| static const int microsecondsPerSecond = |
| microsecondsPerMillisecond * millisecondsPerSecond; |
| |
| /// The number of microseconds per minute. |
| static const int microsecondsPerMinute = |
| microsecondsPerSecond * secondsPerMinute; |
| |
| /// The number of microseconds per hour. |
| static const int microsecondsPerHour = microsecondsPerMinute * minutesPerHour; |
| |
| /// The number of microseconds per day. |
| static const int microsecondsPerDay = microsecondsPerHour * hoursPerDay; |
| |
| /// The number of milliseconds per minute. |
| static const int millisecondsPerMinute = |
| millisecondsPerSecond * secondsPerMinute; |
| |
| /// The number of milliseconds per hour. |
| static const int millisecondsPerHour = millisecondsPerMinute * minutesPerHour; |
| |
| /// The number of milliseconds per day. |
| static const int millisecondsPerDay = millisecondsPerHour * hoursPerDay; |
| |
| /// The number of seconds per hour. |
| static const int secondsPerHour = secondsPerMinute * minutesPerHour; |
| |
| /// The number of seconds per day. |
| static const int secondsPerDay = secondsPerHour * hoursPerDay; |
| |
| /// The number of minutes per day. |
| static const int minutesPerDay = minutesPerHour * hoursPerDay; |
| |
| /// An empty duration, representing zero time. |
| static const Duration zero = Duration(seconds: 0); |
| |
| /// The total microseconds of this [Duration] object. |
| final int _duration; |
| |
| /// Creates a new [Duration] object whose value |
| /// is the sum of all individual parts. |
| /// |
| /// Individual parts can be larger than the number of those |
| /// parts in the next larger unit. |
| /// For example, [hours] can be greater than 23. |
| /// If this happens, the value overflows into the next larger |
| /// unit, so 26 [hours] is the same as 2 [hours] and |
| /// one more [days]. |
| /// Likewise, values can be negative, in which case they |
| /// underflow and subtract from the next larger unit. |
| /// |
| /// If the total number of microseconds cannot be represented |
| /// as an integer value, the number of microseconds might be truncated |
| /// and it might lose precision. |
| /// |
| /// All arguments are 0 by default. |
| const Duration( |
| {int days = 0, |
| int hours = 0, |
| int minutes = 0, |
| int seconds = 0, |
| int milliseconds = 0, |
| int microseconds = 0}) |
| : this._microseconds(microseconds + |
| microsecondsPerMillisecond * milliseconds + |
| microsecondsPerSecond * seconds + |
| microsecondsPerMinute * minutes + |
| microsecondsPerHour * hours + |
| microsecondsPerDay * days); |
| |
| // Fast path internal direct constructor to avoids the optional arguments and |
| // [_microseconds] recomputation. |
| const Duration._microseconds(this._duration); |
| |
| /// Adds this Duration and [other] and |
| /// returns the sum as a new Duration object. |
| Duration operator +(Duration other) { |
| return Duration._microseconds(_duration + other._duration); |
| } |
| |
| /// Subtracts [other] from this Duration and |
| /// returns the difference as a new Duration object. |
| Duration operator -(Duration other) { |
| return Duration._microseconds(_duration - other._duration); |
| } |
| |
| /// Multiplies this Duration by the given [factor] and returns the result |
| /// as a new Duration object. |
| /// |
| /// Note that when [factor] is a double, and the duration is greater than |
| /// 53 bits, precision is lost because of double-precision arithmetic. |
| Duration operator *(num factor) { |
| return Duration._microseconds((_duration * factor).round()); |
| } |
| |
| /// Divides this Duration by the given [quotient] and returns the truncated |
| /// result as a new Duration object. |
| /// |
| /// Throws an [IntegerDivisionByZeroException] if [quotient] is `0`. |
| Duration operator ~/(int quotient) { |
| // By doing the check here instead of relying on "~/" below we get the |
| // exception even with dart2js. |
| if (quotient == 0) throw IntegerDivisionByZeroException(); |
| return Duration._microseconds(_duration ~/ quotient); |
| } |
| |
| /// Whether this [Duration] is shorter than [other]. |
| bool operator <(Duration other) => this._duration < other._duration; |
| |
| /// Whether this [Duration] is longer than [other]. |
| bool operator >(Duration other) => this._duration > other._duration; |
| |
| /// Whether this [Duration] is shorter than or equal to [other]. |
| bool operator <=(Duration other) => this._duration <= other._duration; |
| |
| /// Whether this [Duration] is longer than or equal to [other]. |
| bool operator >=(Duration other) => this._duration >= other._duration; |
| |
| /// The number of entire days spanned by this [Duration]. |
| int get inDays => _duration ~/ Duration.microsecondsPerDay; |
| |
| /// The number of entire hours spanned by this [Duration]. |
| /// |
| /// The returned value can be greater than 23. |
| /// For example a duration of four days and three hours |
| /// has 99 entire hours. |
| int get inHours => _duration ~/ Duration.microsecondsPerHour; |
| |
| /// The number of whole minutes spanned by this [Duration]. |
| /// |
| /// The returned value can be greater than 59. |
| /// For example a duration of three hours and 12 minutes |
| /// has 192 minutes. |
| int get inMinutes => _duration ~/ Duration.microsecondsPerMinute; |
| |
| /// The number of whole seconds spanned by this [Duration]. |
| /// |
| /// The returned value can be greater than 59. |
| /// For example a duration of three minutes and 12 seconds |
| /// has 192 seconds. |
| int get inSeconds => _duration ~/ Duration.microsecondsPerSecond; |
| |
| /// The number of whole milliseconds spanned by this [Duration]. |
| /// |
| /// The returned value can be greater than 999. |
| /// For example a duration of three seconds and 125 milliseconds |
| /// has 3125 milliseconds. |
| int get inMilliseconds => _duration ~/ Duration.microsecondsPerMillisecond; |
| |
| /// The number of whole microseconds spanned by this [Duration]. |
| /// |
| /// The returned value can be greater than 999999. |
| /// For example a duration of three seconds, 125 milliseconds and |
| /// 369 microseconds has 3125369 microseconds. |
| int get inMicroseconds => _duration; |
| |
| /// Whether this [Duration] has the same length as [other]. |
| /// |
| /// Durations have the same length if they have the same number |
| /// of microseconds, as reported by [inMicroseconds]. |
| bool operator ==(Object other) => |
| other is Duration && _duration == other.inMicroseconds; |
| |
| int get hashCode => _duration.hashCode; |
| |
| /// Compares this [Duration] to [other], returning zero if the values are equal. |
| /// |
| /// Returns a negative integer if this [Duration] is shorter than |
| /// [other], or a positive integer if it is longer. |
| /// |
| /// A negative [Duration] is always considered shorter than a positive one. |
| /// |
| /// It is always the case that `duration1.compareTo(duration2) < 0` iff |
| /// `(someDate + duration1).compareTo(someDate + duration2) < 0`. |
| int compareTo(Duration other) => _duration.compareTo(other._duration); |
| |
| /// Returns a string representation of this [Duration]. |
| /// |
| /// Returns a string with hours, minutes, seconds, and microseconds, in the |
| /// following format: `H:MM:SS.mmmmmm`. For example, |
| /// ```dart |
| /// var d = Duration(days: 1, hours: 1, minutes: 33, microseconds: 500); |
| /// d.toString(); // "25:33:00.000500" |
| /// |
| /// d = Duration(days: 0, hours: 1, minutes: 10, microseconds: 500); |
| /// d.toString(); // "1:10:00.000500" |
| /// ``` |
| String toString() { |
| var microseconds = inMicroseconds; |
| |
| var hours = microseconds ~/ microsecondsPerHour; |
| microseconds = microseconds.remainder(microsecondsPerHour); |
| |
| if (microseconds < 0) microseconds = -microseconds; |
| |
| var minutes = microseconds ~/ microsecondsPerMinute; |
| microseconds = microseconds.remainder(microsecondsPerMinute); |
| |
| var minutesPadding = minutes < 10 ? "0" : ""; |
| |
| var seconds = microseconds ~/ microsecondsPerSecond; |
| microseconds = microseconds.remainder(microsecondsPerSecond); |
| |
| var secondsPadding = seconds < 10 ? "0" : ""; |
| |
| var paddedMicroseconds = microseconds.toString().padLeft(6, "0"); |
| return "$hours:" |
| "$minutesPadding$minutes:" |
| "$secondsPadding$seconds.$paddedMicroseconds"; |
| } |
| |
| /// Whether this [Duration] is negative. |
| /// |
| /// A negative [Duration] represents the difference from a later time to an |
| /// earlier time. |
| bool get isNegative => _duration < 0; |
| |
| /// Creates a new [Duration] representing the absolute length of this |
| /// [Duration]. |
| /// |
| /// The returned [Duration] has the same length as this one, but is always |
| /// positive where possible. |
| Duration abs() => Duration._microseconds(_duration.abs()); |
| |
| /// Creates a new [Duration] with the opposite direction of this [Duration]. |
| /// |
| /// The returned [Duration] has the same length as this one, but will have the |
| /// opposite sign (as reported by [isNegative]) as this one where possible. |
| // Using subtraction helps dart2js avoid negative zeros. |
| Duration operator -() => Duration._microseconds(0 - _duration); |
| } |