mirror of
https://github.com/dart-lang/sdk
synced 2024-10-02 23:49:17 +00:00
Revert "[js_runtime, js_dev_runtime] Implement microsecond
field of DataTime
"
This reverts commit fb057ea4e0
.
Reason for revert: b/342552853
Original change's description:
> [js_runtime, js_dev_runtime] Implement `microsecond` field of `DataTime`
>
> - Move DateTime implementation for dart2js and DDC into a shared place to reduce duplication.
>
> - Add a _microsecond field to the web DateTime to track microseconds outside of the JavaScript Date.
>
> - The cute dart2js optimization whereby `DateTime.now().millisecondsSinceEpoch` is compiled to `Date.now()` still works.
>
> - Both implementations report better errors.
>
> - Fixed VM bug with in-range sentinel.
>
>
> Change-Id: I9156255bdb6ecc195500ae9bc88f91fb315b6297
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/366963
> Reviewed-by: Alexander Aprelev <aam@google.com>
> Reviewed-by: Martin Kustermann <kustermann@google.com>
> Reviewed-by: Lasse Nielsen <lrn@google.com>
> Commit-Queue: Stephen Adams <sra@google.com>
Change-Id: I58572256a7710df4589bb5e41c7afee295c2388b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/368103
Reviewed-by: Alexander Thomas <athom@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Auto-Submit: Ivan Inozemtsev <iinozemtsev@google.com>
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
This commit is contained in:
parent
a3f83a9e44
commit
72b2883c6f
14
CHANGELOG.md
14
CHANGELOG.md
|
@ -17,20 +17,6 @@
|
||||||
[#55418]: https://github.com/dart-lang/sdk/issues/55418
|
[#55418]: https://github.com/dart-lang/sdk/issues/55418
|
||||||
[#55436]: https://github.com/dart-lang/sdk/issues/55436
|
[#55436]: https://github.com/dart-lang/sdk/issues/55436
|
||||||
|
|
||||||
### Libraries
|
|
||||||
|
|
||||||
#### `dart:core`
|
|
||||||
|
|
||||||
- `DateTime` on the web platform now stores microseconds. Fixes [#44876][].
|
|
||||||
The web imlementation is now practically compatible with the native
|
|
||||||
implementation. Small discrepancies due to rounding of web integers may still
|
|
||||||
occur for (1) `microsecondsSinceEpoch` outside the safe range, corresponding
|
|
||||||
to dates with a year outside of 1685..2255, and (2) arithmetic (`add`,
|
|
||||||
`subtract`, `difference`) where the `Duration` argument or result exceeds 570
|
|
||||||
years.
|
|
||||||
|
|
||||||
[#44876]: https://github.com/dart-lang/sdk/issues/44876
|
|
||||||
|
|
||||||
### Tools
|
### Tools
|
||||||
|
|
||||||
#### Linter
|
#### Linter
|
||||||
|
|
|
@ -11,7 +11,7 @@ class Foo {
|
||||||
int? x;
|
int? x;
|
||||||
/*member: Foo.:member_unit=4{libB}*/
|
/*member: Foo.:member_unit=4{libB}*/
|
||||||
Foo() {
|
Foo() {
|
||||||
x = DateTime.now().millisecondsSinceEpoch;
|
x = DateTime.now().millisecond;
|
||||||
}
|
}
|
||||||
/*member: Foo.method:member_unit=4{libB}*/
|
/*member: Foo.method:member_unit=4{libB}*/
|
||||||
@pragma('dart2js:noInline')
|
@pragma('dart2js:noInline')
|
||||||
|
|
|
@ -267,6 +267,147 @@ class Error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Patch for DateTime implementation.
|
||||||
|
@patch
|
||||||
|
class DateTime {
|
||||||
|
@patch
|
||||||
|
DateTime.fromMillisecondsSinceEpoch(int millisecondsSinceEpoch,
|
||||||
|
{bool isUtc = false})
|
||||||
|
: this._withValue(millisecondsSinceEpoch, isUtc: isUtc);
|
||||||
|
|
||||||
|
@patch
|
||||||
|
DateTime.fromMicrosecondsSinceEpoch(int microsecondsSinceEpoch,
|
||||||
|
{bool isUtc = false})
|
||||||
|
: this._withValue(
|
||||||
|
_microsecondInRoundedMilliseconds(microsecondsSinceEpoch),
|
||||||
|
isUtc: isUtc);
|
||||||
|
|
||||||
|
@patch
|
||||||
|
DateTime._internal(int year, int month, int day, int hour, int minute,
|
||||||
|
int second, int millisecond, int microsecond, bool isUtc)
|
||||||
|
: isUtc = isUtc,
|
||||||
|
_value = checkInt(Primitives.valueFromDecomposedDate(
|
||||||
|
year,
|
||||||
|
month,
|
||||||
|
day,
|
||||||
|
hour,
|
||||||
|
minute,
|
||||||
|
second,
|
||||||
|
millisecond + _microsecondInRoundedMilliseconds(microsecond),
|
||||||
|
isUtc));
|
||||||
|
|
||||||
|
@patch
|
||||||
|
DateTime._now()
|
||||||
|
: isUtc = false,
|
||||||
|
_value = Primitives.dateNow();
|
||||||
|
|
||||||
|
@patch
|
||||||
|
DateTime._nowUtc()
|
||||||
|
: isUtc = true,
|
||||||
|
_value = Primitives.dateNow();
|
||||||
|
|
||||||
|
/// Rounds the given [microsecond] to the nearest milliseconds value.
|
||||||
|
///
|
||||||
|
/// For example, invoked with argument `2600` returns `3`.
|
||||||
|
static int _microsecondInRoundedMilliseconds(int microsecond) {
|
||||||
|
return (microsecond / 1000).round();
|
||||||
|
}
|
||||||
|
|
||||||
|
@patch
|
||||||
|
static int? _brokenDownDateToValue(int year, int month, int day, int hour,
|
||||||
|
int minute, int second, int millisecond, int microsecond, bool isUtc) {
|
||||||
|
return Primitives.valueFromDecomposedDate(
|
||||||
|
year,
|
||||||
|
month,
|
||||||
|
day,
|
||||||
|
hour,
|
||||||
|
minute,
|
||||||
|
second,
|
||||||
|
millisecond + _microsecondInRoundedMilliseconds(microsecond),
|
||||||
|
isUtc);
|
||||||
|
}
|
||||||
|
|
||||||
|
@patch
|
||||||
|
String get timeZoneName {
|
||||||
|
if (isUtc) return "UTC";
|
||||||
|
return Primitives.getTimeZoneName(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@patch
|
||||||
|
Duration get timeZoneOffset {
|
||||||
|
if (isUtc) return Duration.zero;
|
||||||
|
return Duration(minutes: Primitives.getTimeZoneOffsetInMinutes(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
@patch
|
||||||
|
DateTime add(Duration duration) {
|
||||||
|
return DateTime._withValue(_value + duration.inMilliseconds, isUtc: isUtc);
|
||||||
|
}
|
||||||
|
|
||||||
|
@patch
|
||||||
|
DateTime subtract(Duration duration) {
|
||||||
|
return DateTime._withValue(_value - duration.inMilliseconds, isUtc: isUtc);
|
||||||
|
}
|
||||||
|
|
||||||
|
@patch
|
||||||
|
Duration difference(DateTime other) {
|
||||||
|
return Duration(milliseconds: _value - other.millisecondsSinceEpoch);
|
||||||
|
}
|
||||||
|
|
||||||
|
@patch
|
||||||
|
int get millisecondsSinceEpoch => _value;
|
||||||
|
|
||||||
|
@patch
|
||||||
|
int get microsecondsSinceEpoch => _value * 1000;
|
||||||
|
|
||||||
|
@patch
|
||||||
|
int get year => Primitives.getYear(this);
|
||||||
|
|
||||||
|
@patch
|
||||||
|
int get month => Primitives.getMonth(this);
|
||||||
|
|
||||||
|
@patch
|
||||||
|
int get day => Primitives.getDay(this);
|
||||||
|
|
||||||
|
@patch
|
||||||
|
int get hour => Primitives.getHours(this);
|
||||||
|
|
||||||
|
@patch
|
||||||
|
int get minute => Primitives.getMinutes(this);
|
||||||
|
|
||||||
|
@patch
|
||||||
|
int get second => Primitives.getSeconds(this);
|
||||||
|
|
||||||
|
@patch
|
||||||
|
int get millisecond => Primitives.getMilliseconds(this);
|
||||||
|
|
||||||
|
@patch
|
||||||
|
int get microsecond => 0;
|
||||||
|
|
||||||
|
@patch
|
||||||
|
int get weekday => Primitives.getWeekday(this);
|
||||||
|
|
||||||
|
@patch
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
other is DateTime &&
|
||||||
|
_value == other.millisecondsSinceEpoch &&
|
||||||
|
isUtc == other.isUtc;
|
||||||
|
|
||||||
|
@patch
|
||||||
|
bool isBefore(DateTime other) => _value < other.millisecondsSinceEpoch;
|
||||||
|
|
||||||
|
@patch
|
||||||
|
bool isAfter(DateTime other) => _value > other.millisecondsSinceEpoch;
|
||||||
|
|
||||||
|
@patch
|
||||||
|
bool isAtSameMomentAs(DateTime other) =>
|
||||||
|
_value == other.millisecondsSinceEpoch;
|
||||||
|
|
||||||
|
@patch
|
||||||
|
int compareTo(DateTime other) =>
|
||||||
|
_value.compareTo(other.millisecondsSinceEpoch);
|
||||||
|
}
|
||||||
|
|
||||||
// Patch for Stopwatch implementation.
|
// Patch for Stopwatch implementation.
|
||||||
@patch
|
@patch
|
||||||
class Stopwatch {
|
class Stopwatch {
|
||||||
|
|
|
@ -392,7 +392,6 @@ class Primitives {
|
||||||
@nullCheck int minutes,
|
@nullCheck int minutes,
|
||||||
@nullCheck int seconds,
|
@nullCheck int seconds,
|
||||||
@nullCheck int milliseconds,
|
@nullCheck int milliseconds,
|
||||||
@nullCheck int microseconds,
|
|
||||||
@nullCheck bool isUtc) {
|
@nullCheck bool isUtc) {
|
||||||
final int MAX_MILLISECONDS_SINCE_EPOCH = 8640000000000000;
|
final int MAX_MILLISECONDS_SINCE_EPOCH = 8640000000000000;
|
||||||
var jsMonth = month - 1;
|
var jsMonth = month - 1;
|
||||||
|
@ -404,11 +403,6 @@ class Primitives {
|
||||||
years += 400;
|
years += 400;
|
||||||
jsMonth -= 400 * 12;
|
jsMonth -= 400 * 12;
|
||||||
}
|
}
|
||||||
// JavaScript `Date` does not handle microseconds, so ensure the provided
|
|
||||||
// microseconds is in range [0..999].
|
|
||||||
final remainder = microseconds % 1000;
|
|
||||||
milliseconds += (microseconds - remainder) ~/ 1000;
|
|
||||||
microseconds = remainder;
|
|
||||||
int value;
|
int value;
|
||||||
if (isUtc) {
|
if (isUtc) {
|
||||||
value = JS<int>('!', r'Date.UTC(#, #, #, #, #, #, #)', years, jsMonth,
|
value = JS<int>('!', r'Date.UTC(#, #, #, #, #, #, #)', years, jsMonth,
|
||||||
|
@ -419,13 +413,23 @@ class Primitives {
|
||||||
}
|
}
|
||||||
if (value.isNaN ||
|
if (value.isNaN ||
|
||||||
value < -MAX_MILLISECONDS_SINCE_EPOCH ||
|
value < -MAX_MILLISECONDS_SINCE_EPOCH ||
|
||||||
value > MAX_MILLISECONDS_SINCE_EPOCH ||
|
value > MAX_MILLISECONDS_SINCE_EPOCH) {
|
||||||
value == MAX_MILLISECONDS_SINCE_EPOCH && microseconds != 0) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
if (years <= 0 || years < 100) return patchUpY2K(value, years, isUtc);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int patchUpY2K(value, years, isUtc) {
|
||||||
|
var date = JS<int>('!', r'new Date(#)', value);
|
||||||
|
if (isUtc) {
|
||||||
|
JS<int>('!', r'#.setUTCFullYear(#)', date, years);
|
||||||
|
} else {
|
||||||
|
JS<int>('!', r'#.setFullYear(#)', date, years);
|
||||||
|
}
|
||||||
|
return JS<int>('!', r'#.valueOf()', date);
|
||||||
|
}
|
||||||
|
|
||||||
// Lazily keep a JS Date stored in the JS object.
|
// Lazily keep a JS Date stored in the JS object.
|
||||||
static lazyAsJsDate(DateTime receiver) {
|
static lazyAsJsDate(DateTime receiver) {
|
||||||
if (JS<bool>('!', r'#.date === (void 0)', receiver)) {
|
if (JS<bool>('!', r'#.date === (void 0)', receiver)) {
|
||||||
|
@ -489,6 +493,13 @@ class Primitives {
|
||||||
return (weekday + 6) % 7 + 1;
|
return (weekday + 6) % 7 + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static num valueFromDateString(str) {
|
||||||
|
if (str is! String) throw argumentErrorValue(str);
|
||||||
|
num value = JS('!', r'Date.parse(#)', str);
|
||||||
|
if (value.isNaN) throw argumentErrorValue(str);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
static Object? getProperty(Object? object, Object key) {
|
static Object? getProperty(Object? object, Object key) {
|
||||||
if (object == null || object is bool || object is num || object is String) {
|
if (object == null || object is bool || object is num || object is String) {
|
||||||
throw argumentErrorValue(object);
|
throw argumentErrorValue(object);
|
||||||
|
|
|
@ -281,6 +281,151 @@ class Error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Patch for DateTime implementation.
|
||||||
|
@patch
|
||||||
|
class DateTime {
|
||||||
|
@patch
|
||||||
|
DateTime.fromMillisecondsSinceEpoch(int millisecondsSinceEpoch,
|
||||||
|
{bool isUtc = false})
|
||||||
|
// `0 + millisecondsSinceEpoch` forces the inferred result to be non-null.
|
||||||
|
: this._withValue(0 + millisecondsSinceEpoch, isUtc: isUtc);
|
||||||
|
|
||||||
|
@patch
|
||||||
|
DateTime.fromMicrosecondsSinceEpoch(int microsecondsSinceEpoch,
|
||||||
|
{bool isUtc = false})
|
||||||
|
: this._withValue(
|
||||||
|
_microsecondInRoundedMilliseconds(microsecondsSinceEpoch),
|
||||||
|
isUtc: isUtc);
|
||||||
|
|
||||||
|
@patch
|
||||||
|
DateTime._internal(int year, int month, int day, int hour, int minute,
|
||||||
|
int second, int millisecond, int microsecond, bool isUtc)
|
||||||
|
// checkBool is manually inlined here because dart2js doesn't inline it
|
||||||
|
// and [isUtc] is usually a constant.
|
||||||
|
: this.isUtc =
|
||||||
|
isUtc is bool ? isUtc : throw ArgumentError.value(isUtc, 'isUtc'),
|
||||||
|
_value = checkInt(Primitives.valueFromDecomposedDate(
|
||||||
|
year,
|
||||||
|
month,
|
||||||
|
day,
|
||||||
|
hour,
|
||||||
|
minute,
|
||||||
|
second,
|
||||||
|
millisecond + _microsecondInRoundedMilliseconds(microsecond),
|
||||||
|
isUtc));
|
||||||
|
|
||||||
|
@patch
|
||||||
|
DateTime._now()
|
||||||
|
: isUtc = false,
|
||||||
|
_value = Primitives.dateNow();
|
||||||
|
|
||||||
|
@patch
|
||||||
|
DateTime._nowUtc()
|
||||||
|
: isUtc = true,
|
||||||
|
_value = Primitives.dateNow();
|
||||||
|
|
||||||
|
/// Rounds the given [microsecond] to the nearest milliseconds value.
|
||||||
|
///
|
||||||
|
/// For example, invoked with argument `2600` returns `3`.
|
||||||
|
static int _microsecondInRoundedMilliseconds(int microsecond) {
|
||||||
|
return (microsecond / 1000).round();
|
||||||
|
}
|
||||||
|
|
||||||
|
@patch
|
||||||
|
static int? _brokenDownDateToValue(int year, int month, int day, int hour,
|
||||||
|
int minute, int second, int millisecond, int microsecond, bool isUtc) {
|
||||||
|
return Primitives.valueFromDecomposedDate(
|
||||||
|
year,
|
||||||
|
month,
|
||||||
|
day,
|
||||||
|
hour,
|
||||||
|
minute,
|
||||||
|
second,
|
||||||
|
millisecond + _microsecondInRoundedMilliseconds(microsecond),
|
||||||
|
isUtc);
|
||||||
|
}
|
||||||
|
|
||||||
|
@patch
|
||||||
|
String get timeZoneName {
|
||||||
|
if (isUtc) return "UTC";
|
||||||
|
return Primitives.getTimeZoneName(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@patch
|
||||||
|
Duration get timeZoneOffset {
|
||||||
|
if (isUtc) return Duration();
|
||||||
|
return Duration(minutes: Primitives.getTimeZoneOffsetInMinutes(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
@patch
|
||||||
|
DateTime add(Duration duration) {
|
||||||
|
return DateTime._withValue(_value + duration.inMilliseconds, isUtc: isUtc);
|
||||||
|
}
|
||||||
|
|
||||||
|
@patch
|
||||||
|
DateTime subtract(Duration duration) {
|
||||||
|
return DateTime._withValue(_value - duration.inMilliseconds, isUtc: isUtc);
|
||||||
|
}
|
||||||
|
|
||||||
|
@patch
|
||||||
|
Duration difference(DateTime other) {
|
||||||
|
return Duration(milliseconds: _value - other.millisecondsSinceEpoch);
|
||||||
|
}
|
||||||
|
|
||||||
|
@patch
|
||||||
|
int get millisecondsSinceEpoch => _value;
|
||||||
|
|
||||||
|
@patch
|
||||||
|
int get microsecondsSinceEpoch => 1000 * _value;
|
||||||
|
|
||||||
|
@patch
|
||||||
|
int get year => Primitives.getYear(this);
|
||||||
|
|
||||||
|
@patch
|
||||||
|
int get month => Primitives.getMonth(this);
|
||||||
|
|
||||||
|
@patch
|
||||||
|
int get day => Primitives.getDay(this);
|
||||||
|
|
||||||
|
@patch
|
||||||
|
int get hour => Primitives.getHours(this);
|
||||||
|
|
||||||
|
@patch
|
||||||
|
int get minute => Primitives.getMinutes(this);
|
||||||
|
|
||||||
|
@patch
|
||||||
|
int get second => Primitives.getSeconds(this);
|
||||||
|
|
||||||
|
@patch
|
||||||
|
int get millisecond => Primitives.getMilliseconds(this);
|
||||||
|
|
||||||
|
@patch
|
||||||
|
int get microsecond => 0;
|
||||||
|
|
||||||
|
@patch
|
||||||
|
int get weekday => Primitives.getWeekday(this);
|
||||||
|
|
||||||
|
@patch
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
other is DateTime &&
|
||||||
|
_value == other.millisecondsSinceEpoch &&
|
||||||
|
isUtc == other.isUtc;
|
||||||
|
|
||||||
|
@patch
|
||||||
|
bool isBefore(DateTime other) => _value < other.millisecondsSinceEpoch;
|
||||||
|
|
||||||
|
@patch
|
||||||
|
bool isAfter(DateTime other) => _value > other.millisecondsSinceEpoch;
|
||||||
|
|
||||||
|
@patch
|
||||||
|
bool isAtSameMomentAs(DateTime other) =>
|
||||||
|
_value == other.millisecondsSinceEpoch;
|
||||||
|
|
||||||
|
@patch
|
||||||
|
int compareTo(DateTime other) =>
|
||||||
|
_value.compareTo(other.millisecondsSinceEpoch);
|
||||||
|
}
|
||||||
|
|
||||||
// Patch for Stopwatch implementation.
|
// Patch for Stopwatch implementation.
|
||||||
@patch
|
@patch
|
||||||
class Stopwatch {
|
class Stopwatch {
|
||||||
|
|
|
@ -682,16 +682,8 @@ class Primitives {
|
||||||
as int;
|
as int;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int? valueFromDecomposedDate(
|
static int? valueFromDecomposedDate(int years, int month, int day, int hours,
|
||||||
int years,
|
int minutes, int seconds, int milliseconds, bool isUtc) {
|
||||||
int month,
|
|
||||||
int day,
|
|
||||||
int hours,
|
|
||||||
int minutes,
|
|
||||||
int seconds,
|
|
||||||
int milliseconds,
|
|
||||||
int microseconds,
|
|
||||||
bool isUtc) {
|
|
||||||
final int MAX_MILLISECONDS_SINCE_EPOCH = 8640000000000000;
|
final int MAX_MILLISECONDS_SINCE_EPOCH = 8640000000000000;
|
||||||
checkInt(years);
|
checkInt(years);
|
||||||
checkInt(month);
|
checkInt(month);
|
||||||
|
@ -700,7 +692,6 @@ class Primitives {
|
||||||
checkInt(minutes);
|
checkInt(minutes);
|
||||||
checkInt(seconds);
|
checkInt(seconds);
|
||||||
checkInt(milliseconds);
|
checkInt(milliseconds);
|
||||||
checkInt(microseconds);
|
|
||||||
checkBool(isUtc);
|
checkBool(isUtc);
|
||||||
var jsMonth = month - 1;
|
var jsMonth = month - 1;
|
||||||
// The JavaScript Date constructor 'corrects' year NN to 19NN. Sidestep that
|
// The JavaScript Date constructor 'corrects' year NN to 19NN. Sidestep that
|
||||||
|
@ -711,11 +702,6 @@ class Primitives {
|
||||||
years += 400;
|
years += 400;
|
||||||
jsMonth -= 400 * 12;
|
jsMonth -= 400 * 12;
|
||||||
}
|
}
|
||||||
// JavaScript `Date` does not handle microseconds, so ensure the provided
|
|
||||||
// microseconds is in range [0..999].
|
|
||||||
final remainder = microseconds % 1000;
|
|
||||||
milliseconds += (microseconds - remainder) ~/ 1000;
|
|
||||||
microseconds = remainder;
|
|
||||||
num value;
|
num value;
|
||||||
if (isUtc) {
|
if (isUtc) {
|
||||||
value = JS('num', r'Date.UTC(#, #, #, #, #, #, #)', years, jsMonth, day,
|
value = JS('num', r'Date.UTC(#, #, #, #, #, #, #)', years, jsMonth, day,
|
||||||
|
@ -726,8 +712,7 @@ class Primitives {
|
||||||
}
|
}
|
||||||
if (value.isNaN ||
|
if (value.isNaN ||
|
||||||
value < -MAX_MILLISECONDS_SINCE_EPOCH ||
|
value < -MAX_MILLISECONDS_SINCE_EPOCH ||
|
||||||
value > MAX_MILLISECONDS_SINCE_EPOCH ||
|
value > MAX_MILLISECONDS_SINCE_EPOCH) {
|
||||||
value == MAX_MILLISECONDS_SINCE_EPOCH && microseconds != 0) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return JS('int', '#', value);
|
return JS('int', '#', value);
|
||||||
|
@ -759,7 +744,7 @@ class Primitives {
|
||||||
@pragma('dart2js:noSideEffects')
|
@pragma('dart2js:noSideEffects')
|
||||||
@pragma('dart2js:noThrows')
|
@pragma('dart2js:noThrows')
|
||||||
@pragma('dart2js:noInline')
|
@pragma('dart2js:noInline')
|
||||||
static int getYear(DateTime receiver) {
|
static getYear(DateTime receiver) {
|
||||||
return (receiver.isUtc)
|
return (receiver.isUtc)
|
||||||
? JS('int', r'(#.getUTCFullYear() + 0)', lazyAsJsDate(receiver))
|
? JS('int', r'(#.getUTCFullYear() + 0)', lazyAsJsDate(receiver))
|
||||||
: JS('int', r'(#.getFullYear() + 0)', lazyAsJsDate(receiver));
|
: JS('int', r'(#.getFullYear() + 0)', lazyAsJsDate(receiver));
|
||||||
|
@ -768,7 +753,7 @@ class Primitives {
|
||||||
@pragma('dart2js:noSideEffects')
|
@pragma('dart2js:noSideEffects')
|
||||||
@pragma('dart2js:noThrows')
|
@pragma('dart2js:noThrows')
|
||||||
@pragma('dart2js:noInline')
|
@pragma('dart2js:noInline')
|
||||||
static int getMonth(DateTime receiver) {
|
static getMonth(DateTime receiver) {
|
||||||
return (receiver.isUtc)
|
return (receiver.isUtc)
|
||||||
? JS('JSUInt31', r'#.getUTCMonth() + 1', lazyAsJsDate(receiver))
|
? JS('JSUInt31', r'#.getUTCMonth() + 1', lazyAsJsDate(receiver))
|
||||||
: JS('JSUInt31', r'#.getMonth() + 1', lazyAsJsDate(receiver));
|
: JS('JSUInt31', r'#.getMonth() + 1', lazyAsJsDate(receiver));
|
||||||
|
@ -777,7 +762,7 @@ class Primitives {
|
||||||
@pragma('dart2js:noSideEffects')
|
@pragma('dart2js:noSideEffects')
|
||||||
@pragma('dart2js:noThrows')
|
@pragma('dart2js:noThrows')
|
||||||
@pragma('dart2js:noInline')
|
@pragma('dart2js:noInline')
|
||||||
static int getDay(DateTime receiver) {
|
static getDay(DateTime receiver) {
|
||||||
return (receiver.isUtc)
|
return (receiver.isUtc)
|
||||||
? JS('JSUInt31', r'(#.getUTCDate() + 0)', lazyAsJsDate(receiver))
|
? JS('JSUInt31', r'(#.getUTCDate() + 0)', lazyAsJsDate(receiver))
|
||||||
: JS('JSUInt31', r'(#.getDate() + 0)', lazyAsJsDate(receiver));
|
: JS('JSUInt31', r'(#.getDate() + 0)', lazyAsJsDate(receiver));
|
||||||
|
@ -786,7 +771,7 @@ class Primitives {
|
||||||
@pragma('dart2js:noSideEffects')
|
@pragma('dart2js:noSideEffects')
|
||||||
@pragma('dart2js:noThrows')
|
@pragma('dart2js:noThrows')
|
||||||
@pragma('dart2js:noInline')
|
@pragma('dart2js:noInline')
|
||||||
static int getHours(DateTime receiver) {
|
static getHours(DateTime receiver) {
|
||||||
return (receiver.isUtc)
|
return (receiver.isUtc)
|
||||||
? JS('JSUInt31', r'(#.getUTCHours() + 0)', lazyAsJsDate(receiver))
|
? JS('JSUInt31', r'(#.getUTCHours() + 0)', lazyAsJsDate(receiver))
|
||||||
: JS('JSUInt31', r'(#.getHours() + 0)', lazyAsJsDate(receiver));
|
: JS('JSUInt31', r'(#.getHours() + 0)', lazyAsJsDate(receiver));
|
||||||
|
@ -795,7 +780,7 @@ class Primitives {
|
||||||
@pragma('dart2js:noSideEffects')
|
@pragma('dart2js:noSideEffects')
|
||||||
@pragma('dart2js:noThrows')
|
@pragma('dart2js:noThrows')
|
||||||
@pragma('dart2js:noInline')
|
@pragma('dart2js:noInline')
|
||||||
static int getMinutes(DateTime receiver) {
|
static getMinutes(DateTime receiver) {
|
||||||
return (receiver.isUtc)
|
return (receiver.isUtc)
|
||||||
? JS('JSUInt31', r'(#.getUTCMinutes() + 0)', lazyAsJsDate(receiver))
|
? JS('JSUInt31', r'(#.getUTCMinutes() + 0)', lazyAsJsDate(receiver))
|
||||||
: JS('JSUInt31', r'(#.getMinutes() + 0)', lazyAsJsDate(receiver));
|
: JS('JSUInt31', r'(#.getMinutes() + 0)', lazyAsJsDate(receiver));
|
||||||
|
@ -804,7 +789,7 @@ class Primitives {
|
||||||
@pragma('dart2js:noSideEffects')
|
@pragma('dart2js:noSideEffects')
|
||||||
@pragma('dart2js:noThrows')
|
@pragma('dart2js:noThrows')
|
||||||
@pragma('dart2js:noInline')
|
@pragma('dart2js:noInline')
|
||||||
static int getSeconds(DateTime receiver) {
|
static getSeconds(DateTime receiver) {
|
||||||
return (receiver.isUtc)
|
return (receiver.isUtc)
|
||||||
? JS('JSUInt31', r'(#.getUTCSeconds() + 0)', lazyAsJsDate(receiver))
|
? JS('JSUInt31', r'(#.getUTCSeconds() + 0)', lazyAsJsDate(receiver))
|
||||||
: JS('JSUInt31', r'(#.getSeconds() + 0)', lazyAsJsDate(receiver));
|
: JS('JSUInt31', r'(#.getSeconds() + 0)', lazyAsJsDate(receiver));
|
||||||
|
@ -813,7 +798,7 @@ class Primitives {
|
||||||
@pragma('dart2js:noSideEffects')
|
@pragma('dart2js:noSideEffects')
|
||||||
@pragma('dart2js:noThrows')
|
@pragma('dart2js:noThrows')
|
||||||
@pragma('dart2js:noInline')
|
@pragma('dart2js:noInline')
|
||||||
static int getMilliseconds(DateTime receiver) {
|
static getMilliseconds(DateTime receiver) {
|
||||||
return (receiver.isUtc)
|
return (receiver.isUtc)
|
||||||
? JS(
|
? JS(
|
||||||
'JSUInt31', r'(#.getUTCMilliseconds() + 0)', lazyAsJsDate(receiver))
|
'JSUInt31', r'(#.getUTCMilliseconds() + 0)', lazyAsJsDate(receiver))
|
||||||
|
@ -823,7 +808,7 @@ class Primitives {
|
||||||
@pragma('dart2js:noSideEffects')
|
@pragma('dart2js:noSideEffects')
|
||||||
@pragma('dart2js:noThrows')
|
@pragma('dart2js:noThrows')
|
||||||
@pragma('dart2js:noInline')
|
@pragma('dart2js:noInline')
|
||||||
static int getWeekday(DateTime receiver) {
|
static getWeekday(DateTime receiver) {
|
||||||
int weekday = (receiver.isUtc)
|
int weekday = (receiver.isUtc)
|
||||||
? JS('int', r'#.getUTCDay() + 0', lazyAsJsDate(receiver))
|
? JS('int', r'#.getUTCDay() + 0', lazyAsJsDate(receiver))
|
||||||
: JS('int', r'#.getDay() + 0', lazyAsJsDate(receiver));
|
: JS('int', r'#.getDay() + 0', lazyAsJsDate(receiver));
|
||||||
|
@ -831,6 +816,13 @@ class Primitives {
|
||||||
return (weekday + 6) % 7 + 1;
|
return (weekday + 6) % 7 + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static num valueFromDateString(str) {
|
||||||
|
if (str is! String) throw argumentErrorValue(str);
|
||||||
|
num value = JS('num', r'Date.parse(#)', str);
|
||||||
|
if (value.isNaN) throw argumentErrorValue(str);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
static getProperty(object, key) {
|
static getProperty(object, key) {
|
||||||
if (object == null || object is bool || object is num || object is String) {
|
if (object == null || object is bool || object is num || object is String) {
|
||||||
throw argumentErrorValue(object);
|
throw argumentErrorValue(object);
|
||||||
|
|
|
@ -1,195 +0,0 @@
|
||||||
// Copyright (c) 2024, 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.
|
|
||||||
|
|
||||||
import 'dart:_foreign_helper' show JS;
|
|
||||||
import 'dart:_internal' show patch;
|
|
||||||
import 'dart:_js_helper' show checkInt, Primitives;
|
|
||||||
|
|
||||||
// Patch for DateTime implementation.
|
|
||||||
@patch
|
|
||||||
class DateTime {
|
|
||||||
/// The value component of this DateTime, equal to [millisecondsSinceEpoch].
|
|
||||||
final int _value;
|
|
||||||
|
|
||||||
/// The [microsecond] component of this DateTime, in the range [0...999].
|
|
||||||
final int _microsecond;
|
|
||||||
|
|
||||||
/// Constructor for pre-validated components.
|
|
||||||
DateTime._(this._value, this._microsecond, {required this.isUtc});
|
|
||||||
|
|
||||||
/// Constructs a new [DateTime] instance with the given value.
|
|
||||||
///
|
|
||||||
/// If [isUtc] is false, then the date is in the local time zone.
|
|
||||||
DateTime._withValueChecked(int millisecondsSinceEpoch, int microsecond,
|
|
||||||
{required bool isUtc})
|
|
||||||
: _value = _validate(millisecondsSinceEpoch, microsecond, isUtc),
|
|
||||||
_microsecond = microsecond,
|
|
||||||
this.isUtc = isUtc;
|
|
||||||
|
|
||||||
@patch
|
|
||||||
DateTime.fromMillisecondsSinceEpoch(int millisecondsSinceEpoch,
|
|
||||||
{bool isUtc = false})
|
|
||||||
: this._withValueChecked(millisecondsSinceEpoch, 0, isUtc: isUtc);
|
|
||||||
|
|
||||||
@patch
|
|
||||||
DateTime.fromMicrosecondsSinceEpoch(int microsecondsSinceEpoch,
|
|
||||||
{bool isUtc = false})
|
|
||||||
: this._withValueChecked(
|
|
||||||
(microsecondsSinceEpoch - microsecondsSinceEpoch % 1000) ~/ 1000,
|
|
||||||
microsecondsSinceEpoch % 1000,
|
|
||||||
isUtc: isUtc);
|
|
||||||
|
|
||||||
@patch
|
|
||||||
DateTime._internal(int year, int month, int day, int hour, int minute,
|
|
||||||
int second, int millisecond, int microsecond, bool isUtc)
|
|
||||||
// checkBool is manually inlined here because dart2js doesn't inline it
|
|
||||||
// and [isUtc] is usually a constant.
|
|
||||||
: this.isUtc =
|
|
||||||
isUtc is bool ? isUtc : throw ArgumentError.value(isUtc, 'isUtc'),
|
|
||||||
_value = Primitives.valueFromDecomposedDate(year, month, day, hour,
|
|
||||||
minute, second, millisecond, microsecond, isUtc) ??
|
|
||||||
_sentinel,
|
|
||||||
_microsecond = microsecond % 1000 {
|
|
||||||
if (_value == _sentinel) {
|
|
||||||
throw ArgumentError('($year, $month, $day,'
|
|
||||||
' $hour, $minute, $second, $millisecond, $microsecond)');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static const _sentinel = _maxMillisecondsSinceEpoch * 10;
|
|
||||||
static const _sentinelConstraint = _sentinel < -_maxMillisecondsSinceEpoch ||
|
|
||||||
_sentinel > _maxMillisecondsSinceEpoch;
|
|
||||||
static const _sentinelAssertion = 1 ~/ (_sentinelConstraint ? 1 : 0);
|
|
||||||
|
|
||||||
@patch
|
|
||||||
DateTime._now()
|
|
||||||
: isUtc = false,
|
|
||||||
_value = Primitives.dateNow(),
|
|
||||||
_microsecond = 0;
|
|
||||||
|
|
||||||
@patch
|
|
||||||
DateTime._nowUtc()
|
|
||||||
: isUtc = true,
|
|
||||||
_value = Primitives.dateNow(),
|
|
||||||
_microsecond = 0;
|
|
||||||
|
|
||||||
@patch
|
|
||||||
DateTime _withUtc({required bool isUtc}) {
|
|
||||||
return DateTime._(_value, _microsecond, isUtc: isUtc);
|
|
||||||
}
|
|
||||||
|
|
||||||
@patch
|
|
||||||
static DateTime? _finishParse(int year, int month, int day, int hour,
|
|
||||||
int minute, int second, int millisecond, int microsecond, bool isUtc) {
|
|
||||||
final value = Primitives.valueFromDecomposedDate(year, month, day, hour,
|
|
||||||
minute, second, millisecond, microsecond, isUtc);
|
|
||||||
if (value == null) return null;
|
|
||||||
return DateTime._withValueChecked(value, microsecond, isUtc: isUtc);
|
|
||||||
}
|
|
||||||
|
|
||||||
@patch
|
|
||||||
String get timeZoneName {
|
|
||||||
if (isUtc) return "UTC";
|
|
||||||
return Primitives.getTimeZoneName(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@patch
|
|
||||||
Duration get timeZoneOffset {
|
|
||||||
if (isUtc) return Duration.zero;
|
|
||||||
return Duration(minutes: Primitives.getTimeZoneOffsetInMinutes(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
@patch
|
|
||||||
DateTime add(Duration duration) => _addMicroseconds(duration.inMicroseconds);
|
|
||||||
|
|
||||||
@patch
|
|
||||||
DateTime subtract(Duration duration) =>
|
|
||||||
_addMicroseconds(0 - duration.inMicroseconds);
|
|
||||||
|
|
||||||
DateTime _addMicroseconds(int durationMicroseconds) {
|
|
||||||
final durationLo = durationMicroseconds % 1000;
|
|
||||||
final durationHi = (durationMicroseconds - durationLo) ~/ 1000;
|
|
||||||
final sumLo = _microsecond + durationLo;
|
|
||||||
final microsecond = sumLo % 1000;
|
|
||||||
final carry = (sumLo - microsecond) ~/ 1000;
|
|
||||||
final milliseconds = _value + carry + durationHi;
|
|
||||||
return DateTime._withValueChecked(milliseconds, microsecond, isUtc: isUtc);
|
|
||||||
}
|
|
||||||
|
|
||||||
@patch
|
|
||||||
Duration difference(DateTime other) {
|
|
||||||
final deltaMilliseconds =
|
|
||||||
millisecondsSinceEpoch - other.millisecondsSinceEpoch;
|
|
||||||
final deltaMicroseconds = microsecond - other.microsecond;
|
|
||||||
return Duration(
|
|
||||||
milliseconds: deltaMilliseconds, microseconds: deltaMicroseconds);
|
|
||||||
}
|
|
||||||
|
|
||||||
@patch
|
|
||||||
int get millisecondsSinceEpoch => _value;
|
|
||||||
|
|
||||||
@patch
|
|
||||||
int get microsecondsSinceEpoch => 1000 * _value + _microsecond;
|
|
||||||
|
|
||||||
@patch
|
|
||||||
int get year => Primitives.getYear(this);
|
|
||||||
|
|
||||||
@patch
|
|
||||||
int get month => Primitives.getMonth(this);
|
|
||||||
|
|
||||||
@patch
|
|
||||||
int get day => Primitives.getDay(this);
|
|
||||||
|
|
||||||
@patch
|
|
||||||
int get hour => Primitives.getHours(this);
|
|
||||||
|
|
||||||
@patch
|
|
||||||
int get minute => Primitives.getMinutes(this);
|
|
||||||
|
|
||||||
@patch
|
|
||||||
int get second => Primitives.getSeconds(this);
|
|
||||||
|
|
||||||
@patch
|
|
||||||
int get millisecond => Primitives.getMilliseconds(this);
|
|
||||||
|
|
||||||
@patch
|
|
||||||
int get microsecond => _microsecond;
|
|
||||||
|
|
||||||
@patch
|
|
||||||
int get weekday => Primitives.getWeekday(this);
|
|
||||||
|
|
||||||
@patch
|
|
||||||
bool operator ==(Object other) =>
|
|
||||||
other is DateTime &&
|
|
||||||
millisecondsSinceEpoch == other.millisecondsSinceEpoch &&
|
|
||||||
microsecond == other.microsecond &&
|
|
||||||
isUtc == other.isUtc;
|
|
||||||
|
|
||||||
@patch
|
|
||||||
int get hashCode => Object.hash(_value, _microsecond);
|
|
||||||
|
|
||||||
@patch
|
|
||||||
bool isBefore(DateTime other) =>
|
|
||||||
millisecondsSinceEpoch < other.millisecondsSinceEpoch ||
|
|
||||||
millisecondsSinceEpoch == other.millisecondsSinceEpoch &&
|
|
||||||
microsecond < other.microsecond;
|
|
||||||
|
|
||||||
@patch
|
|
||||||
bool isAfter(DateTime other) =>
|
|
||||||
millisecondsSinceEpoch > other.millisecondsSinceEpoch ||
|
|
||||||
millisecondsSinceEpoch == other.millisecondsSinceEpoch &&
|
|
||||||
microsecond > other.microsecond;
|
|
||||||
|
|
||||||
@patch
|
|
||||||
bool isAtSameMomentAs(DateTime other) =>
|
|
||||||
millisecondsSinceEpoch == other.millisecondsSinceEpoch &&
|
|
||||||
microsecond == other.microsecond;
|
|
||||||
|
|
||||||
@patch
|
|
||||||
int compareTo(DateTime other) {
|
|
||||||
final r = millisecondsSinceEpoch.compareTo(other.millisecondsSinceEpoch);
|
|
||||||
if (r != 0) return r;
|
|
||||||
return microsecond.compareTo(other.microsecond);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -29,21 +29,8 @@ class DateTime {
|
||||||
static const _MONTH_INDEX = 7;
|
static const _MONTH_INDEX = 7;
|
||||||
static const _YEAR_INDEX = 8;
|
static const _YEAR_INDEX = 8;
|
||||||
|
|
||||||
/// The value of this DateTime, equal to [microsecondsSinceEpoch].
|
|
||||||
final int _value;
|
|
||||||
|
|
||||||
List<int>? __parts;
|
List<int>? __parts;
|
||||||
|
|
||||||
/// Constructor for pre-validated components.
|
|
||||||
DateTime._(this._value, {required this.isUtc});
|
|
||||||
|
|
||||||
/// Constructs a new [DateTime] instance with the given value.
|
|
||||||
///
|
|
||||||
/// If [isUtc] is false, then the date is in the local time zone.
|
|
||||||
DateTime._withValue(this._value, {required this.isUtc}) {
|
|
||||||
_validate(millisecondsSinceEpoch, microsecond, isUtc);
|
|
||||||
}
|
|
||||||
|
|
||||||
@patch
|
@patch
|
||||||
DateTime.fromMillisecondsSinceEpoch(int millisecondsSinceEpoch,
|
DateTime.fromMillisecondsSinceEpoch(int millisecondsSinceEpoch,
|
||||||
{bool isUtc = false})
|
{bool isUtc = false})
|
||||||
|
@ -57,10 +44,7 @@ class DateTime {
|
||||||
{bool isUtc = false})
|
{bool isUtc = false})
|
||||||
: this._withValue(microsecondsSinceEpoch, isUtc: isUtc);
|
: this._withValue(microsecondsSinceEpoch, isUtc: isUtc);
|
||||||
|
|
||||||
static const _sentinel = -_maxMicrosecondsSinceEpoch - 1;
|
static const _sentinelMs = -_maxMillisecondsSinceEpoch - 1;
|
||||||
static const _sentinelConstraint = _sentinel < -_maxMicrosecondsSinceEpoch ||
|
|
||||||
_sentinel > _maxMicrosecondsSinceEpoch;
|
|
||||||
static const _sentinelAssertion = 1 ~/ (_sentinelConstraint ? 1 : 0);
|
|
||||||
|
|
||||||
@patch
|
@patch
|
||||||
DateTime._internal(int year, int month, int day, int hour, int minute,
|
DateTime._internal(int year, int month, int day, int hour, int minute,
|
||||||
|
@ -68,11 +52,8 @@ class DateTime {
|
||||||
: this.isUtc = checkNotNullable(isUtc, "isUtc"),
|
: this.isUtc = checkNotNullable(isUtc, "isUtc"),
|
||||||
this._value = _brokenDownDateToValue(year, month, day, hour, minute,
|
this._value = _brokenDownDateToValue(year, month, day, hour, minute,
|
||||||
second, millisecond, microsecond, isUtc) ??
|
second, millisecond, microsecond, isUtc) ??
|
||||||
_sentinel {
|
_sentinelMs {
|
||||||
if (_value == _sentinel) {
|
if (_value == _sentinelMs) throw new ArgumentError();
|
||||||
throw ArgumentError('($year, $month, $day,'
|
|
||||||
' $hour, $minute, $second, $millisecond, $microsecond)');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _validateMilliseconds(int millisecondsSinceEpoch) =>
|
static int _validateMilliseconds(int millisecondsSinceEpoch) =>
|
||||||
|
@ -92,11 +73,6 @@ class DateTime {
|
||||||
: isUtc = true,
|
: isUtc = true,
|
||||||
_value = _getCurrentMicros();
|
_value = _getCurrentMicros();
|
||||||
|
|
||||||
@patch
|
|
||||||
DateTime _withUtc({required bool isUtc}) {
|
|
||||||
return DateTime._(_value, isUtc: isUtc);
|
|
||||||
}
|
|
||||||
|
|
||||||
@patch
|
@patch
|
||||||
String get timeZoneName {
|
String get timeZoneName {
|
||||||
if (isUtc) return "UTC";
|
if (isUtc) return "UTC";
|
||||||
|
@ -105,9 +81,9 @@ class DateTime {
|
||||||
|
|
||||||
@patch
|
@patch
|
||||||
Duration get timeZoneOffset {
|
Duration get timeZoneOffset {
|
||||||
if (isUtc) return Duration();
|
if (isUtc) return new Duration();
|
||||||
int offsetInSeconds = _timeZoneOffsetInSeconds(microsecondsSinceEpoch);
|
int offsetInSeconds = _timeZoneOffsetInSeconds(microsecondsSinceEpoch);
|
||||||
return Duration(seconds: offsetInSeconds);
|
return new Duration(seconds: offsetInSeconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
@patch
|
@patch
|
||||||
|
@ -116,9 +92,6 @@ class DateTime {
|
||||||
_value == other.microsecondsSinceEpoch &&
|
_value == other.microsecondsSinceEpoch &&
|
||||||
isUtc == other.isUtc;
|
isUtc == other.isUtc;
|
||||||
|
|
||||||
@patch
|
|
||||||
int get hashCode => (_value ^ (_value >> 30)) & 0x3FFFFFFF;
|
|
||||||
|
|
||||||
@patch
|
@patch
|
||||||
bool isBefore(DateTime other) => _value < other.microsecondsSinceEpoch;
|
bool isBefore(DateTime other) => _value < other.microsecondsSinceEpoch;
|
||||||
|
|
||||||
|
@ -133,11 +106,11 @@ class DateTime {
|
||||||
int compareTo(DateTime other) =>
|
int compareTo(DateTime other) =>
|
||||||
_value.compareTo(other.microsecondsSinceEpoch);
|
_value.compareTo(other.microsecondsSinceEpoch);
|
||||||
|
|
||||||
/// The first list contains the days until each month in non-leap years. The
|
/** The first list contains the days until each month in non-leap years. The
|
||||||
/// second list contains the days in leap years.
|
* second list contains the days in leap years. */
|
||||||
static const List<List<int>> _DAYS_UNTIL_MONTH = [
|
static const List<List<int>> _DAYS_UNTIL_MONTH = const [
|
||||||
[0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334],
|
const [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334],
|
||||||
[0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335]
|
const [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335]
|
||||||
];
|
];
|
||||||
|
|
||||||
static List<int> _computeUpperPart(int localMicros) {
|
static List<int> _computeUpperPart(int localMicros) {
|
||||||
|
@ -207,7 +180,7 @@ class DateTime {
|
||||||
DateTime.daysPerWeek) +
|
DateTime.daysPerWeek) +
|
||||||
DateTime.monday;
|
DateTime.monday;
|
||||||
|
|
||||||
List<int> list = List<int>.filled(_YEAR_INDEX + 1, 0);
|
List<int> list = new List<int>.filled(_YEAR_INDEX + 1, 0);
|
||||||
list[_MICROSECOND_INDEX] = resultMicrosecond;
|
list[_MICROSECOND_INDEX] = resultMicrosecond;
|
||||||
list[_MILLISECOND_INDEX] = resultMillisecond;
|
list[_MILLISECOND_INDEX] = resultMillisecond;
|
||||||
list[_SECOND_INDEX] = resultSecond;
|
list[_SECOND_INDEX] = resultSecond;
|
||||||
|
@ -226,22 +199,24 @@ class DateTime {
|
||||||
|
|
||||||
@patch
|
@patch
|
||||||
DateTime add(Duration duration) {
|
DateTime add(Duration duration) {
|
||||||
return DateTime._withValue(_value + duration.inMicroseconds, isUtc: isUtc);
|
return new DateTime._withValue(_value + duration.inMicroseconds,
|
||||||
|
isUtc: isUtc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@patch
|
@patch
|
||||||
DateTime subtract(Duration duration) {
|
DateTime subtract(Duration duration) {
|
||||||
return DateTime._withValue(_value - duration.inMicroseconds, isUtc: isUtc);
|
return new DateTime._withValue(_value - duration.inMicroseconds,
|
||||||
|
isUtc: isUtc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@patch
|
@patch
|
||||||
Duration difference(DateTime other) {
|
Duration difference(DateTime other) {
|
||||||
return Duration(microseconds: _value - other.microsecondsSinceEpoch);
|
return new Duration(microseconds: _value - other.microsecondsSinceEpoch);
|
||||||
}
|
}
|
||||||
|
|
||||||
@patch
|
@patch
|
||||||
int get millisecondsSinceEpoch =>
|
int get millisecondsSinceEpoch =>
|
||||||
_flooredDivision(_value, Duration.microsecondsPerMillisecond);
|
_value ~/ Duration.microsecondsPerMillisecond;
|
||||||
|
|
||||||
@patch
|
@patch
|
||||||
int get microsecondsSinceEpoch => _value;
|
int get microsecondsSinceEpoch => _value;
|
||||||
|
@ -273,19 +248,21 @@ class DateTime {
|
||||||
@patch
|
@patch
|
||||||
int get year => _parts[_YEAR_INDEX];
|
int get year => _parts[_YEAR_INDEX];
|
||||||
|
|
||||||
/// Returns the amount of microseconds in UTC that represent the same values
|
/**
|
||||||
/// as this [DateTime].
|
* Returns the amount of microseconds in UTC that represent the same values
|
||||||
///
|
* as this [DateTime].
|
||||||
/// Say `t` is the result of this function, then
|
*
|
||||||
/// * `this.year == new DateTime.fromMicrosecondsSinceEpoch(t, true).year`,
|
* Say `t` is the result of this function, then
|
||||||
/// * `this.month == new DateTime.fromMicrosecondsSinceEpoch(t, true).month`,
|
* * `this.year == new DateTime.fromMicrosecondsSinceEpoch(t, true).year`,
|
||||||
/// * `this.day == new DateTime.fromMicrosecondsSinceEpoch(t, true).day`,
|
* * `this.month == new DateTime.fromMicrosecondsSinceEpoch(t, true).month`,
|
||||||
/// * `this.hour == new DateTime.fromMicrosecondsSinceEpoch(t, true).hour`,
|
* * `this.day == new DateTime.fromMicrosecondsSinceEpoch(t, true).day`,
|
||||||
/// * ...
|
* * `this.hour == new DateTime.fromMicrosecondsSinceEpoch(t, true).hour`,
|
||||||
///
|
* * ...
|
||||||
/// Daylight savings is computed as if the date was computed in [1970..2037].
|
*
|
||||||
/// If this [DateTime] lies outside this range then a year with similar
|
* Daylight savings is computed as if the date was computed in [1970..2037].
|
||||||
/// properties (leap year, weekdays) is used instead.
|
* If this [DateTime] lies outside this range then it is a year with similar
|
||||||
|
* properties (leap year, weekdays) is used instead.
|
||||||
|
*/
|
||||||
int get _localDateInUtcMicros {
|
int get _localDateInUtcMicros {
|
||||||
int micros = _value;
|
int micros = _value;
|
||||||
if (isUtc) return micros;
|
if (isUtc) return micros;
|
||||||
|
@ -313,6 +290,7 @@ class DateTime {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts the given broken down date to microseconds.
|
/// Converts the given broken down date to microseconds.
|
||||||
|
@patch
|
||||||
static int? _brokenDownDateToValue(int year, int month, int day, int hour,
|
static int? _brokenDownDateToValue(int year, int month, int day, int hour,
|
||||||
int minute, int second, int millisecond, int microsecond, bool isUtc) {
|
int minute, int second, int millisecond, int microsecond, bool isUtc) {
|
||||||
// Simplify calculations by working with zero-based month.
|
// Simplify calculations by working with zero-based month.
|
||||||
|
@ -360,26 +338,19 @@ class DateTime {
|
||||||
return microsecondsSinceEpoch;
|
return microsecondsSinceEpoch;
|
||||||
}
|
}
|
||||||
|
|
||||||
@patch
|
|
||||||
static DateTime? _finishParse(int year, int month, int day, int hour,
|
|
||||||
int minute, int second, int millisecond, int microsecond, bool isUtc) {
|
|
||||||
final value = _brokenDownDateToValue(year, month, day, hour, minute, second,
|
|
||||||
millisecond, microsecond, isUtc);
|
|
||||||
if (value == null) return null;
|
|
||||||
return DateTime._withValue(value, isUtc: isUtc);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _weekDay(y) {
|
static int _weekDay(y) {
|
||||||
// 1/1/1970 was a Thursday.
|
// 1/1/1970 was a Thursday.
|
||||||
return (_dayFromYear(y) + 4) % 7;
|
return (_dayFromYear(y) + 4) % 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a year in the range 2008-2035 matching
|
/**
|
||||||
/// * leap year, and
|
* Returns a year in the range 2008-2035 matching
|
||||||
/// * week day of first day.
|
* * leap year, and
|
||||||
///
|
* * week day of first day.
|
||||||
/// Leap seconds are ignored.
|
*
|
||||||
/// Adapted from V8's date implementation. See ECMA 262 - 15.9.1.9.
|
* Leap seconds are ignored.
|
||||||
|
* Adapted from V8's date implementation. See ECMA 262 - 15.9.1.9.
|
||||||
|
*/
|
||||||
static int _equivalentYear(int year) {
|
static int _equivalentYear(int year) {
|
||||||
// Returns year y so that _weekDay(y) == _weekDay(year).
|
// Returns year y so that _weekDay(y) == _weekDay(year).
|
||||||
// _weekDay returns the week day (in range 0 - 6).
|
// _weekDay returns the week day (in range 0 - 6).
|
||||||
|
@ -399,10 +370,12 @@ class DateTime {
|
||||||
return 2008 + (recentYear - 2008) % 28;
|
return 2008 + (recentYear - 2008) % 28;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the UTC year for the corresponding [secondsSinceEpoch].
|
/**
|
||||||
/// It is relatively fast for values in the range 0 to year 2098.
|
* Returns the UTC year for the corresponding [secondsSinceEpoch].
|
||||||
///
|
* It is relatively fast for values in the range 0 to year 2098.
|
||||||
/// Code is adapted from V8.
|
*
|
||||||
|
* Code is adapted from V8.
|
||||||
|
*/
|
||||||
static int _yearsFromSecondsSinceEpoch(int secondsSinceEpoch) {
|
static int _yearsFromSecondsSinceEpoch(int secondsSinceEpoch) {
|
||||||
const int DAYS_IN_4_YEARS = 4 * 365 + 1;
|
const int DAYS_IN_4_YEARS = 4 * 365 + 1;
|
||||||
const int DAYS_IN_100_YEARS = 25 * DAYS_IN_4_YEARS - 1;
|
const int DAYS_IN_100_YEARS = 25 * DAYS_IN_4_YEARS - 1;
|
||||||
|
@ -417,16 +390,18 @@ class DateTime {
|
||||||
return _computeUpperPart(micros)[_YEAR_INDEX];
|
return _computeUpperPart(micros)[_YEAR_INDEX];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a date in seconds that is equivalent to the given
|
/**
|
||||||
/// date in microseconds [microsecondsSinceEpoch]. An equivalent
|
* Returns a date in seconds that is equivalent to the given
|
||||||
/// date has the same fields (`month`, `day`, etc.) as the given
|
* date in microseconds [microsecondsSinceEpoch]. An equivalent
|
||||||
/// date, but the `year` is in the range [1901..2038].
|
* date has the same fields (`month`, `day`, etc.) as the given
|
||||||
///
|
* date, but the `year` is in the range [1901..2038].
|
||||||
/// * The time since the beginning of the year is the same.
|
*
|
||||||
/// * If the given date is in a leap year then the returned
|
* * The time since the beginning of the year is the same.
|
||||||
/// seconds are in a leap year, too.
|
* * If the given date is in a leap year then the returned
|
||||||
/// * The week day of given date is the same as the one for the
|
* seconds are in a leap year, too.
|
||||||
/// returned date.
|
* * The week day of given date is the same as the one for the
|
||||||
|
* returned date.
|
||||||
|
*/
|
||||||
static int _equivalentSeconds(int microsecondsSinceEpoch) {
|
static int _equivalentSeconds(int microsecondsSinceEpoch) {
|
||||||
const int CUT_OFF_SECONDS = 0x7FFFFFFF;
|
const int CUT_OFF_SECONDS = 0x7FFFFFFF;
|
||||||
|
|
||||||
|
|
|
@ -159,6 +159,13 @@ class DateTime implements Comparable<DateTime> {
|
||||||
static const int december = 12;
|
static const int december = 12;
|
||||||
static const int monthsPerYear = 12;
|
static const int monthsPerYear = 12;
|
||||||
|
|
||||||
|
/// The value of this DateTime.
|
||||||
|
///
|
||||||
|
/// The content of this field is implementation dependent. On JavaScript it is
|
||||||
|
/// equal to [millisecondsSinceEpoch]. On the VM it is equal to
|
||||||
|
/// [microsecondsSinceEpoch].
|
||||||
|
final int _value;
|
||||||
|
|
||||||
/// True if this [DateTime] is set to UTC time.
|
/// True if this [DateTime] is set to UTC time.
|
||||||
///
|
///
|
||||||
/// ```dart
|
/// ```dart
|
||||||
|
@ -341,12 +348,12 @@ class DateTime implements Comparable<DateTime> {
|
||||||
minute -= sign * minuteDifference;
|
minute -= sign * minuteDifference;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DateTime? result = _finishParse(years, month, day, hour, minute, second,
|
int? value = _brokenDownDateToValue(years, month, day, hour, minute,
|
||||||
millisecond, microsecond, isUtc);
|
second, millisecond, microsecond, isUtc);
|
||||||
if (result == null) {
|
if (value == null) {
|
||||||
throw FormatException("Time out of range", formattedString);
|
throw FormatException("Time out of range", formattedString);
|
||||||
}
|
}
|
||||||
return result;
|
return DateTime._withValue(value, isUtc: isUtc);
|
||||||
} else {
|
} else {
|
||||||
throw FormatException("Invalid date format", formattedString);
|
throw FormatException("Invalid date format", formattedString);
|
||||||
}
|
}
|
||||||
|
@ -366,8 +373,6 @@ class DateTime implements Comparable<DateTime> {
|
||||||
}
|
}
|
||||||
|
|
||||||
static const int _maxMillisecondsSinceEpoch = 8640000000000000;
|
static const int _maxMillisecondsSinceEpoch = 8640000000000000;
|
||||||
static const int _maxMicrosecondsSinceEpoch =
|
|
||||||
_maxMillisecondsSinceEpoch * Duration.microsecondsPerMillisecond;
|
|
||||||
|
|
||||||
/// Constructs a new [DateTime] instance
|
/// Constructs a new [DateTime] instance
|
||||||
/// with the given [millisecondsSinceEpoch].
|
/// with the given [millisecondsSinceEpoch].
|
||||||
|
@ -401,33 +406,18 @@ class DateTime implements Comparable<DateTime> {
|
||||||
external DateTime.fromMicrosecondsSinceEpoch(int microsecondsSinceEpoch,
|
external DateTime.fromMicrosecondsSinceEpoch(int microsecondsSinceEpoch,
|
||||||
{bool isUtc = false});
|
{bool isUtc = false});
|
||||||
|
|
||||||
/// Throws an error if the millisecondsSinceEpoch and microsecond components
|
/// Constructs a new [DateTime] instance with the given value.
|
||||||
/// are out of range.
|
|
||||||
///
|
///
|
||||||
/// Returns the millisecondsSinceEpoch component.
|
/// If [isUtc] is false, then the date is in the local time zone.
|
||||||
static int _validate(
|
DateTime._withValue(this._value, {required this.isUtc}) {
|
||||||
int millisecondsSinceEpoch, int microsecond, bool isUtc) {
|
if (millisecondsSinceEpoch.abs() > _maxMillisecondsSinceEpoch ||
|
||||||
if (microsecond < 0 || microsecond > 999) {
|
(millisecondsSinceEpoch.abs() == _maxMillisecondsSinceEpoch &&
|
||||||
throw RangeError.range(microsecond, 0, 999, "microsecond");
|
microsecond != 0)) {
|
||||||
|
throw ArgumentError(
|
||||||
|
"DateTime is outside valid range: $millisecondsSinceEpoch");
|
||||||
}
|
}
|
||||||
if (millisecondsSinceEpoch < -_maxMillisecondsSinceEpoch ||
|
|
||||||
millisecondsSinceEpoch > _maxMillisecondsSinceEpoch) {
|
|
||||||
throw RangeError.range(
|
|
||||||
millisecondsSinceEpoch,
|
|
||||||
-_maxMillisecondsSinceEpoch,
|
|
||||||
_maxMillisecondsSinceEpoch,
|
|
||||||
"millisecondsSinceEpoch");
|
|
||||||
}
|
|
||||||
if (millisecondsSinceEpoch == _maxMillisecondsSinceEpoch &&
|
|
||||||
microsecond != 0) {
|
|
||||||
throw ArgumentError.value(microsecond, "microsecond",
|
|
||||||
"Time including microseconds is outside valid range");
|
|
||||||
}
|
|
||||||
|
|
||||||
// For backwards compatibility with legacy mode.
|
// For backwards compatibility with legacy mode.
|
||||||
checkNotNullable(isUtc, "isUtc");
|
checkNotNullable(isUtc, "isUtc");
|
||||||
|
|
||||||
return millisecondsSinceEpoch;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether [other] is a [DateTime] at the same moment and in the
|
/// Whether [other] is a [DateTime] at the same moment and in the
|
||||||
|
@ -446,8 +436,6 @@ class DateTime implements Comparable<DateTime> {
|
||||||
/// independently of their zones.
|
/// independently of their zones.
|
||||||
external bool operator ==(Object other);
|
external bool operator ==(Object other);
|
||||||
|
|
||||||
external int get hashCode;
|
|
||||||
|
|
||||||
/// Whether this [DateTime] occurs before [other].
|
/// Whether this [DateTime] occurs before [other].
|
||||||
///
|
///
|
||||||
/// The comparison is independent
|
/// The comparison is independent
|
||||||
|
@ -528,6 +516,8 @@ class DateTime implements Comparable<DateTime> {
|
||||||
/// ```
|
/// ```
|
||||||
external int compareTo(DateTime other);
|
external int compareTo(DateTime other);
|
||||||
|
|
||||||
|
int get hashCode => (_value ^ (_value >> 30)) & 0x3FFFFFFF;
|
||||||
|
|
||||||
/// Returns this DateTime value in the local time zone.
|
/// Returns this DateTime value in the local time zone.
|
||||||
///
|
///
|
||||||
/// Returns this [DateTime] if it is already in the local time zone.
|
/// Returns this [DateTime] if it is already in the local time zone.
|
||||||
|
@ -539,7 +529,7 @@ class DateTime implements Comparable<DateTime> {
|
||||||
/// ```
|
/// ```
|
||||||
DateTime toLocal() {
|
DateTime toLocal() {
|
||||||
if (isUtc) {
|
if (isUtc) {
|
||||||
return _withUtc(isUtc: false);
|
return DateTime._withValue(_value, isUtc: false);
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -555,11 +545,9 @@ class DateTime implements Comparable<DateTime> {
|
||||||
/// ```
|
/// ```
|
||||||
DateTime toUtc() {
|
DateTime toUtc() {
|
||||||
if (isUtc) return this;
|
if (isUtc) return this;
|
||||||
return _withUtc(isUtc: true);
|
return DateTime._withValue(_value, isUtc: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
external DateTime _withUtc({required bool isUtc});
|
|
||||||
|
|
||||||
static String _fourDigits(int n) {
|
static String _fourDigits(int n) {
|
||||||
int absN = n.abs();
|
int absN = n.abs();
|
||||||
String sign = n < 0 ? "-" : "";
|
String sign = n < 0 ? "-" : "";
|
||||||
|
@ -724,10 +712,18 @@ class DateTime implements Comparable<DateTime> {
|
||||||
|
|
||||||
external DateTime._now();
|
external DateTime._now();
|
||||||
|
|
||||||
/// Returns the [DateTime] corresponding to the given components, or `null` if
|
/// Returns the time as value (millisecond or microsecond since epoch), or
|
||||||
/// the values are out of range.
|
/// null if the values are out of range.
|
||||||
external static DateTime? _finishParse(int year, int month, int day, int hour,
|
external static int? _brokenDownDateToValue(
|
||||||
int minute, int second, int millisecond, int microsecond, bool isUtc);
|
int year,
|
||||||
|
int month,
|
||||||
|
int day,
|
||||||
|
int hour,
|
||||||
|
int minute,
|
||||||
|
int second,
|
||||||
|
int millisecond,
|
||||||
|
int microsecond,
|
||||||
|
bool isUtc);
|
||||||
|
|
||||||
/// The number of milliseconds since
|
/// The number of milliseconds since
|
||||||
/// the "Unix epoch" 1970-01-01T00:00:00Z (UTC).
|
/// the "Unix epoch" 1970-01-01T00:00:00Z (UTC).
|
||||||
|
@ -748,10 +744,8 @@ class DateTime implements Comparable<DateTime> {
|
||||||
/// 8,640,000,000,000,000,000us (100,000,000 days) from the Unix epoch.
|
/// 8,640,000,000,000,000,000us (100,000,000 days) from the Unix epoch.
|
||||||
/// In other words: `microsecondsSinceEpoch.abs() <= 8640000000000000000`.
|
/// In other words: `microsecondsSinceEpoch.abs() <= 8640000000000000000`.
|
||||||
///
|
///
|
||||||
/// Note that this value does not always fit into 53 bits (the size of a IEEE
|
/// Note that this value does not fit into 53 bits (the size of a IEEE double).
|
||||||
/// double). On the web JavaScript platforms, there may be a rounding error
|
/// A JavaScript number is not able to hold this value.
|
||||||
/// for DateTime values sufficiently far from the epoch. The year range close
|
|
||||||
/// to the epoch to avoid rounding is approximately 1685..2254.
|
|
||||||
external int get microsecondsSinceEpoch;
|
external int get microsecondsSinceEpoch;
|
||||||
|
|
||||||
/// The time zone name.
|
/// The time zone name.
|
||||||
|
|
|
@ -390,10 +390,7 @@
|
||||||
},
|
},
|
||||||
"core": {
|
"core": {
|
||||||
"uri": "core/core.dart",
|
"uri": "core/core.dart",
|
||||||
"patches": [
|
"patches": "_internal/js_runtime/lib/core_patch.dart"
|
||||||
"_internal/js_shared/lib/date_time_patch.dart",
|
|
||||||
"_internal/js_runtime/lib/core_patch.dart"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"developer": {
|
"developer": {
|
||||||
"uri": "developer/developer.dart",
|
"uri": "developer/developer.dart",
|
||||||
|
@ -573,10 +570,7 @@
|
||||||
},
|
},
|
||||||
"core": {
|
"core": {
|
||||||
"uri": "core/core.dart",
|
"uri": "core/core.dart",
|
||||||
"patches": [
|
"patches": "_internal/js_dev_runtime/patch/core_patch.dart"
|
||||||
"_internal/js_shared/lib/date_time_patch.dart",
|
|
||||||
"_internal/js_dev_runtime/patch/core_patch.dart"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"developer": {
|
"developer": {
|
||||||
"uri": "developer/developer.dart",
|
"uri": "developer/developer.dart",
|
||||||
|
|
|
@ -319,9 +319,7 @@ _dart2js_common:
|
||||||
|
|
||||||
core:
|
core:
|
||||||
uri: "core/core.dart"
|
uri: "core/core.dart"
|
||||||
patches:
|
patches: "_internal/js_runtime/lib/core_patch.dart"
|
||||||
- "_internal/js_shared/lib/date_time_patch.dart"
|
|
||||||
- "_internal/js_runtime/lib/core_patch.dart"
|
|
||||||
|
|
||||||
developer:
|
developer:
|
||||||
uri: "developer/developer.dart"
|
uri: "developer/developer.dart"
|
||||||
|
@ -497,9 +495,7 @@ dartdevc:
|
||||||
|
|
||||||
core:
|
core:
|
||||||
uri: "core/core.dart"
|
uri: "core/core.dart"
|
||||||
patches:
|
patches: "_internal/js_dev_runtime/patch/core_patch.dart"
|
||||||
- "_internal/js_shared/lib/date_time_patch.dart"
|
|
||||||
- "_internal/js_dev_runtime/patch/core_patch.dart"
|
|
||||||
|
|
||||||
developer:
|
developer:
|
||||||
uri: "developer/developer.dart"
|
uri: "developer/developer.dart"
|
||||||
|
|
|
@ -7,13 +7,14 @@ import "package:expect/expect.dart";
|
||||||
// Dart test program for DateTime, extreme values.
|
// Dart test program for DateTime, extreme values.
|
||||||
|
|
||||||
bool get supportsMicroseconds =>
|
bool get supportsMicroseconds =>
|
||||||
DateTime.fromMicrosecondsSinceEpoch(1).microsecondsSinceEpoch == 1;
|
new DateTime.fromMicrosecondsSinceEpoch(1).microsecondsSinceEpoch == 1;
|
||||||
|
|
||||||
// Identical to _maxMillisecondsSinceEpoch in date_time.dart
|
// Identical to _maxMillisecondsSinceEpoch in date_time.dart
|
||||||
const int _MAX_MILLISECONDS = 8640000000000000;
|
const int _MAX_MILLISECONDS = 8640000000000000;
|
||||||
|
|
||||||
void testExtremes() {
|
void testExtremes() {
|
||||||
var dt = DateTime.fromMillisecondsSinceEpoch(_MAX_MILLISECONDS, isUtc: true);
|
var dt =
|
||||||
|
new DateTime.fromMillisecondsSinceEpoch(_MAX_MILLISECONDS, isUtc: true);
|
||||||
Expect.equals(275760, dt.year);
|
Expect.equals(275760, dt.year);
|
||||||
Expect.equals(9, dt.month);
|
Expect.equals(9, dt.month);
|
||||||
Expect.equals(13, dt.day);
|
Expect.equals(13, dt.day);
|
||||||
|
@ -22,7 +23,7 @@ void testExtremes() {
|
||||||
Expect.equals(0, dt.second);
|
Expect.equals(0, dt.second);
|
||||||
Expect.equals(0, dt.millisecond);
|
Expect.equals(0, dt.millisecond);
|
||||||
Expect.equals(0, dt.microsecond);
|
Expect.equals(0, dt.microsecond);
|
||||||
dt = DateTime.fromMillisecondsSinceEpoch(-_MAX_MILLISECONDS, isUtc: true);
|
dt = new DateTime.fromMillisecondsSinceEpoch(-_MAX_MILLISECONDS, isUtc: true);
|
||||||
Expect.equals(-271821, dt.year);
|
Expect.equals(-271821, dt.year);
|
||||||
Expect.equals(4, dt.month);
|
Expect.equals(4, dt.month);
|
||||||
Expect.equals(20, dt.day);
|
Expect.equals(20, dt.day);
|
||||||
|
@ -32,103 +33,71 @@ void testExtremes() {
|
||||||
Expect.equals(0, dt.millisecond);
|
Expect.equals(0, dt.millisecond);
|
||||||
Expect.equals(0, dt.microsecond);
|
Expect.equals(0, dt.microsecond);
|
||||||
// Make sure that we can build the extreme dates in local too.
|
// Make sure that we can build the extreme dates in local too.
|
||||||
dt = DateTime.fromMillisecondsSinceEpoch(_MAX_MILLISECONDS);
|
dt = new DateTime.fromMillisecondsSinceEpoch(_MAX_MILLISECONDS);
|
||||||
dt = DateTime(
|
dt = new DateTime(
|
||||||
dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, dt.millisecond);
|
dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, dt.millisecond);
|
||||||
Expect.equals(_MAX_MILLISECONDS, dt.millisecondsSinceEpoch);
|
Expect.equals(_MAX_MILLISECONDS, dt.millisecondsSinceEpoch);
|
||||||
dt = DateTime.fromMillisecondsSinceEpoch(-_MAX_MILLISECONDS);
|
dt = new DateTime.fromMillisecondsSinceEpoch(-_MAX_MILLISECONDS);
|
||||||
dt = DateTime(
|
dt = new DateTime(
|
||||||
dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, dt.millisecond);
|
dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, dt.millisecond);
|
||||||
Expect.equals(-_MAX_MILLISECONDS, dt.millisecondsSinceEpoch);
|
Expect.equals(-_MAX_MILLISECONDS, dt.millisecondsSinceEpoch);
|
||||||
|
Expect.throws(() => new DateTime.fromMillisecondsSinceEpoch(
|
||||||
|
_MAX_MILLISECONDS + 1,
|
||||||
|
isUtc: true));
|
||||||
|
Expect.throws(() => new DateTime.fromMillisecondsSinceEpoch(
|
||||||
|
-_MAX_MILLISECONDS - 1,
|
||||||
|
isUtc: true));
|
||||||
|
Expect.throws(
|
||||||
|
() => new DateTime.fromMillisecondsSinceEpoch(_MAX_MILLISECONDS + 1));
|
||||||
|
Expect.throws(
|
||||||
|
() => new DateTime.fromMillisecondsSinceEpoch(-_MAX_MILLISECONDS - 1));
|
||||||
|
dt = new DateTime.fromMillisecondsSinceEpoch(_MAX_MILLISECONDS);
|
||||||
|
Expect.throws(
|
||||||
|
() => new DateTime(dt.year, dt.month, dt.day, dt.hour, dt.minute, 0, 1));
|
||||||
|
dt = new DateTime.fromMillisecondsSinceEpoch(_MAX_MILLISECONDS, isUtc: true);
|
||||||
Expect.throws(() =>
|
Expect.throws(() =>
|
||||||
DateTime.fromMillisecondsSinceEpoch(_MAX_MILLISECONDS + 1, isUtc: true));
|
new DateTime.utc(dt.year, dt.month, dt.day, dt.hour, dt.minute, 0, 1));
|
||||||
|
dt = new DateTime.fromMillisecondsSinceEpoch(-_MAX_MILLISECONDS);
|
||||||
|
Expect.throws(
|
||||||
|
() => new DateTime(dt.year, dt.month, dt.day, dt.hour, dt.minute, 0, -1));
|
||||||
|
dt = new DateTime.fromMillisecondsSinceEpoch(-_MAX_MILLISECONDS, isUtc: true);
|
||||||
Expect.throws(() =>
|
Expect.throws(() =>
|
||||||
DateTime.fromMillisecondsSinceEpoch(-_MAX_MILLISECONDS - 1, isUtc: true));
|
new DateTime.utc(dt.year, dt.month, dt.day, dt.hour, dt.minute, 0, -1));
|
||||||
Expect.throws(
|
|
||||||
() => DateTime.fromMillisecondsSinceEpoch(_MAX_MILLISECONDS + 1));
|
|
||||||
Expect.throws(
|
|
||||||
() => DateTime.fromMillisecondsSinceEpoch(-_MAX_MILLISECONDS - 1));
|
|
||||||
dt = DateTime.fromMillisecondsSinceEpoch(_MAX_MILLISECONDS);
|
|
||||||
Expect.throws(
|
|
||||||
() => DateTime(dt.year, dt.month, dt.day, dt.hour, dt.minute, 0, 1));
|
|
||||||
dt = DateTime.fromMillisecondsSinceEpoch(_MAX_MILLISECONDS, isUtc: true);
|
|
||||||
Expect.throws(
|
|
||||||
() => DateTime.utc(dt.year, dt.month, dt.day, dt.hour, dt.minute, 0, 1));
|
|
||||||
dt = DateTime.fromMillisecondsSinceEpoch(-_MAX_MILLISECONDS);
|
|
||||||
Expect.throws(
|
|
||||||
() => DateTime(dt.year, dt.month, dt.day, dt.hour, dt.minute, 0, -1));
|
|
||||||
dt = DateTime.fromMillisecondsSinceEpoch(-_MAX_MILLISECONDS, isUtc: true);
|
|
||||||
Expect.throws(
|
|
||||||
() => DateTime.utc(dt.year, dt.month, dt.day, dt.hour, dt.minute, 0, -1));
|
|
||||||
|
|
||||||
if (!supportsMicroseconds) return;
|
if (!supportsMicroseconds) return;
|
||||||
|
|
||||||
/// The nearest value to [base] in the direction [delta]. For native `int`s,
|
dt = new DateTime.fromMicrosecondsSinceEpoch(_MAX_MILLISECONDS * 1000);
|
||||||
/// this is just `base + delta`. For web `int`s outside the safe range, the
|
dt = new DateTime(dt.year, dt.month, dt.day, dt.hour, dt.minute);
|
||||||
/// next value might differ by some power of two.
|
|
||||||
int nearest(int base, int delta) {
|
|
||||||
for (int factor = 1;; factor *= 2) {
|
|
||||||
final next = base + delta * factor;
|
|
||||||
print(factor);
|
|
||||||
if (next != base) return next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dt = DateTime.fromMicrosecondsSinceEpoch(_MAX_MILLISECONDS * 1000);
|
|
||||||
dt = DateTime(dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second);
|
|
||||||
Expect.equals(_MAX_MILLISECONDS * 1000, dt.microsecondsSinceEpoch);
|
Expect.equals(_MAX_MILLISECONDS * 1000, dt.microsecondsSinceEpoch);
|
||||||
print(-_MAX_MILLISECONDS * 1000);
|
dt = new DateTime.fromMicrosecondsSinceEpoch(-_MAX_MILLISECONDS * 1000);
|
||||||
dt = DateTime.fromMicrosecondsSinceEpoch(-_MAX_MILLISECONDS * 1000);
|
dt = new DateTime(dt.year, dt.month, dt.day, dt.hour, dt.minute);
|
||||||
dt = DateTime(dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second);
|
|
||||||
Expect.equals(-_MAX_MILLISECONDS * 1000, dt.microsecondsSinceEpoch);
|
Expect.equals(-_MAX_MILLISECONDS * 1000, dt.microsecondsSinceEpoch);
|
||||||
Expect.throws(() => DateTime.fromMicrosecondsSinceEpoch(
|
Expect.throws(() => new DateTime.fromMicrosecondsSinceEpoch(
|
||||||
nearest(_MAX_MILLISECONDS * 1000, 1),
|
_MAX_MILLISECONDS * 1000 + 1,
|
||||||
isUtc: true));
|
isUtc: true));
|
||||||
Expect.throws(() => DateTime.fromMicrosecondsSinceEpoch(
|
Expect.throws(() => new DateTime.fromMicrosecondsSinceEpoch(
|
||||||
nearest(-_MAX_MILLISECONDS * 1000, -1),
|
-_MAX_MILLISECONDS * 1000 - 1,
|
||||||
isUtc: true));
|
isUtc: true));
|
||||||
Expect.throws(() => DateTime.fromMicrosecondsSinceEpoch(
|
|
||||||
nearest(_MAX_MILLISECONDS * 1000, 1)));
|
|
||||||
Expect.throws(() => DateTime.fromMicrosecondsSinceEpoch(
|
|
||||||
nearest(-_MAX_MILLISECONDS * 1000, -1)));
|
|
||||||
// These should all succeed - stepping into the valid range rather than out:
|
|
||||||
DateTime.fromMicrosecondsSinceEpoch(nearest(-_MAX_MILLISECONDS * 1000, 1),
|
|
||||||
isUtc: true);
|
|
||||||
DateTime.fromMicrosecondsSinceEpoch(nearest(_MAX_MILLISECONDS * 1000, -1),
|
|
||||||
isUtc: true);
|
|
||||||
DateTime.fromMicrosecondsSinceEpoch(nearest(-_MAX_MILLISECONDS * 1000, 1));
|
|
||||||
DateTime.fromMicrosecondsSinceEpoch(nearest(_MAX_MILLISECONDS * 1000, -1));
|
|
||||||
|
|
||||||
dt = DateTime.fromMillisecondsSinceEpoch(_MAX_MILLISECONDS);
|
|
||||||
Expect.throws(
|
|
||||||
() => DateTime(dt.year, dt.month, dt.day, dt.hour, dt.minute, 0, 0, 1));
|
|
||||||
Expect.throws(() => dt.copyWith(microsecond: 1));
|
|
||||||
Expect.isTrue(dt.copyWith(microsecond: -1).toString().endsWith('.999999'));
|
|
||||||
|
|
||||||
dt = DateTime.fromMillisecondsSinceEpoch(_MAX_MILLISECONDS, isUtc: true);
|
|
||||||
Expect.throws(() =>
|
Expect.throws(() =>
|
||||||
DateTime.utc(dt.year, dt.month, dt.day, dt.hour, dt.minute, 0, 0, 1));
|
new DateTime.fromMicrosecondsSinceEpoch(_MAX_MILLISECONDS * 1000 + 1));
|
||||||
Expect.throws(() => dt.copyWith(microsecond: 1));
|
|
||||||
Expect.isTrue(dt.copyWith(microsecond: -1).toString().endsWith('.999999Z'));
|
|
||||||
|
|
||||||
dt = DateTime.fromMillisecondsSinceEpoch(-_MAX_MILLISECONDS);
|
|
||||||
Expect.throws(
|
|
||||||
() => DateTime(dt.year, dt.month, dt.day, dt.hour, dt.minute, 0, 0, -1));
|
|
||||||
Expect.throws(() => dt.copyWith(microsecond: -1));
|
|
||||||
Expect.isTrue(dt.copyWith(microsecond: 1).toString().endsWith('.000001'));
|
|
||||||
|
|
||||||
dt = DateTime.fromMillisecondsSinceEpoch(-_MAX_MILLISECONDS, isUtc: true);
|
|
||||||
Expect.throws(() =>
|
Expect.throws(() =>
|
||||||
DateTime.utc(dt.year, dt.month, dt.day, dt.hour, dt.minute, 0, 0, -1));
|
new DateTime.fromMicrosecondsSinceEpoch(-_MAX_MILLISECONDS * 1000 - 1));
|
||||||
Expect.throws(() => dt.copyWith(microsecond: -1));
|
dt = new DateTime.fromMillisecondsSinceEpoch(_MAX_MILLISECONDS);
|
||||||
Expect.isTrue(dt.copyWith(microsecond: 1).toString().endsWith('.000001Z'));
|
Expect.throws(() =>
|
||||||
|
new DateTime(dt.year, dt.month, dt.day, dt.hour, dt.minute, 0, 0, 1));
|
||||||
|
dt = new DateTime.fromMillisecondsSinceEpoch(_MAX_MILLISECONDS, isUtc: true);
|
||||||
|
Expect.throws(() =>
|
||||||
|
new DateTime.utc(dt.year, dt.month, dt.day, dt.hour, dt.minute, 0, 0, 1));
|
||||||
|
dt = new DateTime.fromMillisecondsSinceEpoch(-_MAX_MILLISECONDS);
|
||||||
|
Expect.throws(() =>
|
||||||
|
new DateTime(dt.year, dt.month, dt.day, dt.hour, dt.minute, 0, 0, -1));
|
||||||
|
dt = new DateTime.fromMillisecondsSinceEpoch(-_MAX_MILLISECONDS, isUtc: true);
|
||||||
|
Expect.throws(() => new DateTime.utc(
|
||||||
|
dt.year, dt.month, dt.day, dt.hour, dt.minute, 0, 0, -1));
|
||||||
|
|
||||||
// Regression test for https://dartbug.com/55438
|
// Regression test for https://dartbug.com/55438
|
||||||
dt = DateTime.utc(1969, 12, 31, 23, 59, 59, 999, 999);
|
dt = DateTime.utc(1969, 12, 31, 23, 59, 59, 999, 999);
|
||||||
Expect.equals(-1, dt.microsecondsSinceEpoch);
|
Expect.equals(-1, dt.microsecondsSinceEpoch);
|
||||||
// The first fix confused millisecondsSinceEpoch and microsecondsSinceEpoch.
|
|
||||||
dt = DateTime.utc(1696, 3, 16, 23, 59, 59, 999, 999);
|
|
||||||
Expect.equals(-_MAX_MILLISECONDS - 1, dt.microsecondsSinceEpoch);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
Loading…
Reference in a new issue