mirror of
https://github.com/dart-lang/sdk
synced 2024-10-04 17:14:57 +00:00
8fbd651c49
Fixes #27597 BUG= http://dartbug.com/27597 R=lrn@google.com Review URL: https://codereview.chromium.org/2423993002 .
300 lines
9.8 KiB
Dart
300 lines
9.8 KiB
Dart
// 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:
|
|
*
|
|
* Duration fastestMarathon = new 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, [minutes] can be greater than 59.
|
|
*
|
|
* 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,
|
|
*
|
|
* Duration aLongWeekend = new 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> {
|
|
static const int MICROSECONDS_PER_MILLISECOND = 1000;
|
|
static const int MILLISECONDS_PER_SECOND = 1000;
|
|
static const int SECONDS_PER_MINUTE = 60;
|
|
static const int MINUTES_PER_HOUR = 60;
|
|
static const int HOURS_PER_DAY = 24;
|
|
|
|
static const int MICROSECONDS_PER_SECOND =
|
|
MICROSECONDS_PER_MILLISECOND * MILLISECONDS_PER_SECOND;
|
|
static const int MICROSECONDS_PER_MINUTE =
|
|
MICROSECONDS_PER_SECOND * SECONDS_PER_MINUTE;
|
|
static const int MICROSECONDS_PER_HOUR =
|
|
MICROSECONDS_PER_MINUTE * MINUTES_PER_HOUR;
|
|
static const int MICROSECONDS_PER_DAY =
|
|
MICROSECONDS_PER_HOUR * HOURS_PER_DAY;
|
|
|
|
|
|
static const int MILLISECONDS_PER_MINUTE =
|
|
MILLISECONDS_PER_SECOND * SECONDS_PER_MINUTE;
|
|
static const int MILLISECONDS_PER_HOUR =
|
|
MILLISECONDS_PER_MINUTE * MINUTES_PER_HOUR;
|
|
static const int MILLISECONDS_PER_DAY =
|
|
MILLISECONDS_PER_HOUR * HOURS_PER_DAY;
|
|
|
|
static const int SECONDS_PER_HOUR = SECONDS_PER_MINUTE * MINUTES_PER_HOUR;
|
|
static const int SECONDS_PER_DAY = SECONDS_PER_HOUR * HOURS_PER_DAY;
|
|
|
|
static const int MINUTES_PER_DAY = MINUTES_PER_HOUR * HOURS_PER_DAY;
|
|
|
|
static const Duration ZERO = const Duration(seconds: 0);
|
|
|
|
/*
|
|
* The value of this Duration object in microseconds.
|
|
*/
|
|
final int _duration;
|
|
|
|
/**
|
|
* Creates a new Duration object whose value
|
|
* is the sum of all individual parts.
|
|
*
|
|
* Individual parts can be larger than the next-bigger unit.
|
|
* For example, [hours] can be greater than 23.
|
|
*
|
|
* All individual parts are allowed to be negative.
|
|
* 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_PER_DAY * days +
|
|
MICROSECONDS_PER_HOUR * hours +
|
|
MICROSECONDS_PER_MINUTE * minutes +
|
|
MICROSECONDS_PER_SECOND * seconds +
|
|
MICROSECONDS_PER_MILLISECOND * milliseconds +
|
|
microseconds);
|
|
|
|
// 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 new Duration._microseconds(_duration + other._duration);
|
|
}
|
|
|
|
/**
|
|
* Subtracts [other] from this Duration and
|
|
* returns the difference as a new Duration object.
|
|
*/
|
|
Duration operator -(Duration other) {
|
|
return new 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 new 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 new IntegerDivisionByZeroException();
|
|
return new Duration._microseconds(_duration ~/ quotient);
|
|
}
|
|
|
|
/**
|
|
* Returns `true` if the value of this Duration
|
|
* is less than the value of [other].
|
|
*/
|
|
bool operator <(Duration other) => this._duration < other._duration;
|
|
|
|
/**
|
|
* Returns `true` if the value of this Duration
|
|
* is greater than the value of [other].
|
|
*/
|
|
bool operator >(Duration other) => this._duration > other._duration;
|
|
|
|
/**
|
|
* Returns `true` if the value of this Duration
|
|
* is less than or equal to the value of [other].
|
|
*/
|
|
bool operator <=(Duration other) => this._duration <= other._duration;
|
|
|
|
/**
|
|
* Returns `true` if the value of this Duration
|
|
* is greater than or equal to the value of [other].
|
|
*/
|
|
bool operator >=(Duration other) => this._duration >= other._duration;
|
|
|
|
/**
|
|
* Returns the number of whole days spanned by this Duration.
|
|
*/
|
|
int get inDays => _duration ~/ Duration.MICROSECONDS_PER_DAY;
|
|
|
|
/**
|
|
* Returns the number of whole hours spanned by this Duration.
|
|
*
|
|
* The returned value can be greater than 23.
|
|
*/
|
|
int get inHours => _duration ~/ Duration.MICROSECONDS_PER_HOUR;
|
|
|
|
/**
|
|
* Returns the number of whole minutes spanned by this Duration.
|
|
*
|
|
* The returned value can be greater than 59.
|
|
*/
|
|
int get inMinutes => _duration ~/ Duration.MICROSECONDS_PER_MINUTE;
|
|
|
|
/**
|
|
* Returns the number of whole seconds spanned by this Duration.
|
|
*
|
|
* The returned value can be greater than 59.
|
|
*/
|
|
int get inSeconds => _duration ~/ Duration.MICROSECONDS_PER_SECOND;
|
|
|
|
/**
|
|
* Returns number of whole milliseconds spanned by this Duration.
|
|
*
|
|
* The returned value can be greater than 999.
|
|
*/
|
|
int get inMilliseconds => _duration ~/ Duration.MICROSECONDS_PER_MILLISECOND;
|
|
|
|
/**
|
|
* Returns number of whole microseconds spanned by this Duration.
|
|
*/
|
|
int get inMicroseconds => _duration;
|
|
|
|
/**
|
|
* Returns `true` if this Duration is the same object as [other].
|
|
*/
|
|
bool operator ==(other) {
|
|
if (other is !Duration) return false;
|
|
return _duration == other._duration;
|
|
}
|
|
|
|
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: `HH:MM:SS.mmmmmm`. For example,
|
|
*
|
|
* var d = new Duration(days:1, hours:1, minutes:33, microseconds: 500);
|
|
* d.toString(); // "25:33:00.000500"
|
|
*/
|
|
String toString() {
|
|
String sixDigits(int n) {
|
|
if (n >= 100000) return "$n";
|
|
if (n >= 10000) return "0$n";
|
|
if (n >= 1000) return "00$n";
|
|
if (n >= 100) return "000$n";
|
|
if (n >= 10) return "0000$n";
|
|
return "00000$n";
|
|
}
|
|
String twoDigits(int n) {
|
|
if (n >= 10) return "$n";
|
|
return "0$n";
|
|
}
|
|
|
|
if (inMicroseconds < 0) {
|
|
return "-${-this}";
|
|
}
|
|
String twoDigitMinutes = twoDigits(inMinutes.remainder(MINUTES_PER_HOUR));
|
|
String twoDigitSeconds = twoDigits(inSeconds.remainder(SECONDS_PER_MINUTE));
|
|
String sixDigitUs =
|
|
sixDigits(inMicroseconds.remainder(MICROSECONDS_PER_SECOND));
|
|
return "$inHours:$twoDigitMinutes:$twoDigitSeconds.$sixDigitUs";
|
|
}
|
|
|
|
/**
|
|
* Returns whether this `Duration` is negative.
|
|
*
|
|
* A negative `Duration` represents the difference from a later time to an
|
|
* earlier time.
|
|
*/
|
|
bool get isNegative => _duration < 0;
|
|
|
|
/**
|
|
* Returns a new `Duration` representing the absolute value of this
|
|
* `Duration`.
|
|
*
|
|
* The returned `Duration` has the same length as this one, but is always
|
|
* positive.
|
|
*/
|
|
Duration abs() => new Duration._microseconds(_duration.abs());
|
|
|
|
/**
|
|
* Returns a new `Duration` representing this `Duration` negated.
|
|
*
|
|
* The returned `Duration` has the same length as this one, but will have the
|
|
* opposite sign of this one.
|
|
*/
|
|
Duration operator -() => new Duration._microseconds(-_duration);
|
|
}
|