Revert "[js_runtime, js_dev_runtime] Implement `microsecond` field of `DataTime`"

This reverts commit fb057ea4e07de2af624688455925c0ca07afe04f.

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>
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cdc5cfc..78ba51e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,20 +17,6 @@
 [#55418]: https://github.com/dart-lang/sdk/issues/55418
 [#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
 
 #### Linter
diff --git a/pkg/compiler/test/deferred_loading/data/lazy_types/lib.dart b/pkg/compiler/test/deferred_loading/data/lazy_types/lib.dart
index f028c43..751b18c 100644
--- a/pkg/compiler/test/deferred_loading/data/lazy_types/lib.dart
+++ b/pkg/compiler/test/deferred_loading/data/lazy_types/lib.dart
@@ -11,7 +11,7 @@
   int? x;
   /*member: Foo.:member_unit=4{libB}*/
   Foo() {
-    x = DateTime.now().millisecondsSinceEpoch;
+    x = DateTime.now().millisecond;
   }
   /*member: Foo.method:member_unit=4{libB}*/
   @pragma('dart2js:noInline')
diff --git a/sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart
index 65cc146..7c39178 100644
--- a/sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart
+++ b/sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart
@@ -267,6 +267,147 @@
   }
 }
 
+// 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
 class Stopwatch {
diff --git a/sdk/lib/_internal/js_dev_runtime/private/js_helper.dart b/sdk/lib/_internal/js_dev_runtime/private/js_helper.dart
index 6e7c363..2c1c1a0 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/js_helper.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/js_helper.dart
@@ -392,7 +392,6 @@
       @nullCheck int minutes,
       @nullCheck int seconds,
       @nullCheck int milliseconds,
-      @nullCheck int microseconds,
       @nullCheck bool isUtc) {
     final int MAX_MILLISECONDS_SINCE_EPOCH = 8640000000000000;
     var jsMonth = month - 1;
@@ -404,11 +403,6 @@
       years += 400;
       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;
     if (isUtc) {
       value = JS<int>('!', r'Date.UTC(#, #, #, #, #, #, #)', years, jsMonth,
@@ -419,13 +413,23 @@
     }
     if (value.isNaN ||
         value < -MAX_MILLISECONDS_SINCE_EPOCH ||
-        value > MAX_MILLISECONDS_SINCE_EPOCH ||
-        value == MAX_MILLISECONDS_SINCE_EPOCH && microseconds != 0) {
+        value > MAX_MILLISECONDS_SINCE_EPOCH) {
       return null;
     }
+    if (years <= 0 || years < 100) return patchUpY2K(value, years, isUtc);
     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.
   static lazyAsJsDate(DateTime receiver) {
     if (JS<bool>('!', r'#.date === (void 0)', receiver)) {
@@ -489,6 +493,13 @@
     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) {
     if (object == null || object is bool || object is num || object is String) {
       throw argumentErrorValue(object);
diff --git a/sdk/lib/_internal/js_runtime/lib/core_patch.dart b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
index d7aa5f8..db471fb 100644
--- a/sdk/lib/_internal/js_runtime/lib/core_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
@@ -281,6 +281,151 @@
   }
 }
 
+// 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
 class Stopwatch {
diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
index 2359738..1a04a33 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
@@ -682,16 +682,8 @@
         as int;
   }
 
-  static int? valueFromDecomposedDate(
-      int years,
-      int month,
-      int day,
-      int hours,
-      int minutes,
-      int seconds,
-      int milliseconds,
-      int microseconds,
-      bool isUtc) {
+  static int? valueFromDecomposedDate(int years, int month, int day, int hours,
+      int minutes, int seconds, int milliseconds, bool isUtc) {
     final int MAX_MILLISECONDS_SINCE_EPOCH = 8640000000000000;
     checkInt(years);
     checkInt(month);
@@ -700,7 +692,6 @@
     checkInt(minutes);
     checkInt(seconds);
     checkInt(milliseconds);
-    checkInt(microseconds);
     checkBool(isUtc);
     var jsMonth = month - 1;
     // The JavaScript Date constructor 'corrects' year NN to 19NN. Sidestep that
@@ -711,11 +702,6 @@
       years += 400;
       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;
     if (isUtc) {
       value = JS('num', r'Date.UTC(#, #, #, #, #, #, #)', years, jsMonth, day,
@@ -726,8 +712,7 @@
     }
     if (value.isNaN ||
         value < -MAX_MILLISECONDS_SINCE_EPOCH ||
-        value > MAX_MILLISECONDS_SINCE_EPOCH ||
-        value == MAX_MILLISECONDS_SINCE_EPOCH && microseconds != 0) {
+        value > MAX_MILLISECONDS_SINCE_EPOCH) {
       return null;
     }
     return JS('int', '#', value);
@@ -759,7 +744,7 @@
   @pragma('dart2js:noSideEffects')
   @pragma('dart2js:noThrows')
   @pragma('dart2js:noInline')
-  static int getYear(DateTime receiver) {
+  static getYear(DateTime receiver) {
     return (receiver.isUtc)
         ? JS('int', r'(#.getUTCFullYear() + 0)', lazyAsJsDate(receiver))
         : JS('int', r'(#.getFullYear() + 0)', lazyAsJsDate(receiver));
@@ -768,7 +753,7 @@
   @pragma('dart2js:noSideEffects')
   @pragma('dart2js:noThrows')
   @pragma('dart2js:noInline')
-  static int getMonth(DateTime receiver) {
+  static getMonth(DateTime receiver) {
     return (receiver.isUtc)
         ? JS('JSUInt31', r'#.getUTCMonth() + 1', lazyAsJsDate(receiver))
         : JS('JSUInt31', r'#.getMonth() + 1', lazyAsJsDate(receiver));
@@ -777,7 +762,7 @@
   @pragma('dart2js:noSideEffects')
   @pragma('dart2js:noThrows')
   @pragma('dart2js:noInline')
-  static int getDay(DateTime receiver) {
+  static getDay(DateTime receiver) {
     return (receiver.isUtc)
         ? JS('JSUInt31', r'(#.getUTCDate() + 0)', lazyAsJsDate(receiver))
         : JS('JSUInt31', r'(#.getDate() + 0)', lazyAsJsDate(receiver));
@@ -786,7 +771,7 @@
   @pragma('dart2js:noSideEffects')
   @pragma('dart2js:noThrows')
   @pragma('dart2js:noInline')
-  static int getHours(DateTime receiver) {
+  static getHours(DateTime receiver) {
     return (receiver.isUtc)
         ? JS('JSUInt31', r'(#.getUTCHours() + 0)', lazyAsJsDate(receiver))
         : JS('JSUInt31', r'(#.getHours() + 0)', lazyAsJsDate(receiver));
@@ -795,7 +780,7 @@
   @pragma('dart2js:noSideEffects')
   @pragma('dart2js:noThrows')
   @pragma('dart2js:noInline')
-  static int getMinutes(DateTime receiver) {
+  static getMinutes(DateTime receiver) {
     return (receiver.isUtc)
         ? JS('JSUInt31', r'(#.getUTCMinutes() + 0)', lazyAsJsDate(receiver))
         : JS('JSUInt31', r'(#.getMinutes() + 0)', lazyAsJsDate(receiver));
@@ -804,7 +789,7 @@
   @pragma('dart2js:noSideEffects')
   @pragma('dart2js:noThrows')
   @pragma('dart2js:noInline')
-  static int getSeconds(DateTime receiver) {
+  static getSeconds(DateTime receiver) {
     return (receiver.isUtc)
         ? JS('JSUInt31', r'(#.getUTCSeconds() + 0)', lazyAsJsDate(receiver))
         : JS('JSUInt31', r'(#.getSeconds() + 0)', lazyAsJsDate(receiver));
@@ -813,7 +798,7 @@
   @pragma('dart2js:noSideEffects')
   @pragma('dart2js:noThrows')
   @pragma('dart2js:noInline')
-  static int getMilliseconds(DateTime receiver) {
+  static getMilliseconds(DateTime receiver) {
     return (receiver.isUtc)
         ? JS(
             'JSUInt31', r'(#.getUTCMilliseconds() + 0)', lazyAsJsDate(receiver))
@@ -823,7 +808,7 @@
   @pragma('dart2js:noSideEffects')
   @pragma('dart2js:noThrows')
   @pragma('dart2js:noInline')
-  static int getWeekday(DateTime receiver) {
+  static getWeekday(DateTime receiver) {
     int weekday = (receiver.isUtc)
         ? JS('int', r'#.getUTCDay() + 0', lazyAsJsDate(receiver))
         : JS('int', r'#.getDay() + 0', lazyAsJsDate(receiver));
@@ -831,6 +816,13 @@
     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) {
     if (object == null || object is bool || object is num || object is String) {
       throw argumentErrorValue(object);
diff --git a/sdk/lib/_internal/js_shared/lib/date_time_patch.dart b/sdk/lib/_internal/js_shared/lib/date_time_patch.dart
deleted file mode 100644
index ecba740..0000000
--- a/sdk/lib/_internal/js_shared/lib/date_time_patch.dart
+++ /dev/null
@@ -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);
-  }
-}
diff --git a/sdk/lib/_internal/vm_shared/lib/date_patch.dart b/sdk/lib/_internal/vm_shared/lib/date_patch.dart
index 1f06867..b1fd03d 100644
--- a/sdk/lib/_internal/vm_shared/lib/date_patch.dart
+++ b/sdk/lib/_internal/vm_shared/lib/date_patch.dart
@@ -29,21 +29,8 @@
   static const _MONTH_INDEX = 7;
   static const _YEAR_INDEX = 8;
 
-  /// The value of this DateTime, equal to [microsecondsSinceEpoch].
-  final int _value;
-
   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
   DateTime.fromMillisecondsSinceEpoch(int millisecondsSinceEpoch,
       {bool isUtc = false})
@@ -57,10 +44,7 @@
       {bool isUtc = false})
       : this._withValue(microsecondsSinceEpoch, isUtc: isUtc);
 
-  static const _sentinel = -_maxMicrosecondsSinceEpoch - 1;
-  static const _sentinelConstraint = _sentinel < -_maxMicrosecondsSinceEpoch ||
-      _sentinel > _maxMicrosecondsSinceEpoch;
-  static const _sentinelAssertion = 1 ~/ (_sentinelConstraint ? 1 : 0);
+  static const _sentinelMs = -_maxMillisecondsSinceEpoch - 1;
 
   @patch
   DateTime._internal(int year, int month, int day, int hour, int minute,
@@ -68,11 +52,8 @@
       : this.isUtc = checkNotNullable(isUtc, "isUtc"),
         this._value = _brokenDownDateToValue(year, month, day, hour, minute,
                 second, millisecond, microsecond, isUtc) ??
-            _sentinel {
-    if (_value == _sentinel) {
-      throw ArgumentError('($year, $month, $day,'
-          ' $hour, $minute, $second, $millisecond, $microsecond)');
-    }
+            _sentinelMs {
+    if (_value == _sentinelMs) throw new ArgumentError();
   }
 
   static int _validateMilliseconds(int millisecondsSinceEpoch) =>
@@ -93,11 +74,6 @@
         _value = _getCurrentMicros();
 
   @patch
-  DateTime _withUtc({required bool isUtc}) {
-    return DateTime._(_value, isUtc: isUtc);
-  }
-
-  @patch
   String get timeZoneName {
     if (isUtc) return "UTC";
     return _timeZoneName(microsecondsSinceEpoch);
@@ -105,9 +81,9 @@
 
   @patch
   Duration get timeZoneOffset {
-    if (isUtc) return Duration();
+    if (isUtc) return new Duration();
     int offsetInSeconds = _timeZoneOffsetInSeconds(microsecondsSinceEpoch);
-    return Duration(seconds: offsetInSeconds);
+    return new Duration(seconds: offsetInSeconds);
   }
 
   @patch
@@ -117,9 +93,6 @@
       isUtc == other.isUtc;
 
   @patch
-  int get hashCode => (_value ^ (_value >> 30)) & 0x3FFFFFFF;
-
-  @patch
   bool isBefore(DateTime other) => _value < other.microsecondsSinceEpoch;
 
   @patch
@@ -133,11 +106,11 @@
   int compareTo(DateTime other) =>
       _value.compareTo(other.microsecondsSinceEpoch);
 
-  /// The first list contains the days until each month in non-leap years. The
-  /// second list contains the days in leap years.
-  static const List<List<int>> _DAYS_UNTIL_MONTH = [
-    [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334],
-    [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335]
+  /** The first list contains the days until each month in non-leap years. The
+    * second list contains the days in leap years. */
+  static const List<List<int>> _DAYS_UNTIL_MONTH = const [
+    const [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334],
+    const [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335]
   ];
 
   static List<int> _computeUpperPart(int localMicros) {
@@ -207,7 +180,7 @@
             DateTime.daysPerWeek) +
         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[_MILLISECOND_INDEX] = resultMillisecond;
     list[_SECOND_INDEX] = resultSecond;
@@ -226,22 +199,24 @@
 
   @patch
   DateTime add(Duration duration) {
-    return DateTime._withValue(_value + duration.inMicroseconds, isUtc: isUtc);
+    return new DateTime._withValue(_value + duration.inMicroseconds,
+        isUtc: isUtc);
   }
 
   @patch
   DateTime subtract(Duration duration) {
-    return DateTime._withValue(_value - duration.inMicroseconds, isUtc: isUtc);
+    return new DateTime._withValue(_value - duration.inMicroseconds,
+        isUtc: isUtc);
   }
 
   @patch
   Duration difference(DateTime other) {
-    return Duration(microseconds: _value - other.microsecondsSinceEpoch);
+    return new Duration(microseconds: _value - other.microsecondsSinceEpoch);
   }
 
   @patch
   int get millisecondsSinceEpoch =>
-      _flooredDivision(_value, Duration.microsecondsPerMillisecond);
+      _value ~/ Duration.microsecondsPerMillisecond;
 
   @patch
   int get microsecondsSinceEpoch => _value;
@@ -273,19 +248,21 @@
   @patch
   int get year => _parts[_YEAR_INDEX];
 
-  /// 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`,
-  /// * `this.month == new DateTime.fromMicrosecondsSinceEpoch(t, true).month`,
-  /// * `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
-  /// properties (leap year, weekdays) is used instead.
+  /**
+   * 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`,
+   * * `this.month == new DateTime.fromMicrosecondsSinceEpoch(t, true).month`,
+   * * `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 it is a year with similar
+   * properties (leap year, weekdays) is used instead.
+   */
   int get _localDateInUtcMicros {
     int micros = _value;
     if (isUtc) return micros;
@@ -313,6 +290,7 @@
   }
 
   /// Converts the given broken down date to microseconds.
+  @patch
   static int? _brokenDownDateToValue(int year, int month, int day, int hour,
       int minute, int second, int millisecond, int microsecond, bool isUtc) {
     // Simplify calculations by working with zero-based month.
@@ -360,26 +338,19 @@
     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) {
     // 1/1/1970 was a Thursday.
     return (_dayFromYear(y) + 4) % 7;
   }
 
-  /// Returns a year in the range 2008-2035 matching
-  /// * 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.
+  /**
+   * Returns a year in the range 2008-2035 matching
+   * * 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.
+   */
   static int _equivalentYear(int year) {
     // Returns year y so that _weekDay(y) == _weekDay(year).
     // _weekDay returns the week day (in range 0 - 6).
@@ -399,10 +370,12 @@
     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.
-  ///
-  /// Code is adapted from V8.
+  /**
+   * 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.
+   */
   static int _yearsFromSecondsSinceEpoch(int secondsSinceEpoch) {
     const int DAYS_IN_4_YEARS = 4 * 365 + 1;
     const int DAYS_IN_100_YEARS = 25 * DAYS_IN_4_YEARS - 1;
@@ -417,16 +390,18 @@
     return _computeUpperPart(micros)[_YEAR_INDEX];
   }
 
-  /// Returns a date in seconds that is equivalent to the given
-  /// date in microseconds [microsecondsSinceEpoch]. An equivalent
-  /// 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
-  ///   seconds are in a leap year, too.
-  /// * The week day of given date is the same as the one for the
-  ///   returned date.
+  /**
+   * Returns a date in seconds that is equivalent to the given
+   * date in microseconds [microsecondsSinceEpoch]. An equivalent
+   * 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
+   *   seconds are in a leap year, too.
+   * * The week day of given date is the same as the one for the
+   *   returned date.
+   */
   static int _equivalentSeconds(int microsecondsSinceEpoch) {
     const int CUT_OFF_SECONDS = 0x7FFFFFFF;
 
diff --git a/sdk/lib/core/date_time.dart b/sdk/lib/core/date_time.dart
index 6c53f7f..366995c 100644
--- a/sdk/lib/core/date_time.dart
+++ b/sdk/lib/core/date_time.dart
@@ -159,6 +159,13 @@
   static const int december = 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.
   ///
   /// ```dart
@@ -341,12 +348,12 @@
           minute -= sign * minuteDifference;
         }
       }
-      DateTime? result = _finishParse(years, month, day, hour, minute, second,
-          millisecond, microsecond, isUtc);
-      if (result == null) {
+      int? value = _brokenDownDateToValue(years, month, day, hour, minute,
+          second, millisecond, microsecond, isUtc);
+      if (value == null) {
         throw FormatException("Time out of range", formattedString);
       }
-      return result;
+      return DateTime._withValue(value, isUtc: isUtc);
     } else {
       throw FormatException("Invalid date format", formattedString);
     }
@@ -366,8 +373,6 @@
   }
 
   static const int _maxMillisecondsSinceEpoch = 8640000000000000;
-  static const int _maxMicrosecondsSinceEpoch =
-      _maxMillisecondsSinceEpoch * Duration.microsecondsPerMillisecond;
 
   /// Constructs a new [DateTime] instance
   /// with the given [millisecondsSinceEpoch].
@@ -401,33 +406,18 @@
   external DateTime.fromMicrosecondsSinceEpoch(int microsecondsSinceEpoch,
       {bool isUtc = false});
 
-  /// Throws an error if the millisecondsSinceEpoch and microsecond components
-  /// are out of range.
+  /// Constructs a new [DateTime] instance with the given value.
   ///
-  /// Returns the millisecondsSinceEpoch component.
-  static int _validate(
-      int millisecondsSinceEpoch, int microsecond, bool isUtc) {
-    if (microsecond < 0 || microsecond > 999) {
-      throw RangeError.range(microsecond, 0, 999, "microsecond");
+  /// If [isUtc] is false, then the date is in the local time zone.
+  DateTime._withValue(this._value, {required this.isUtc}) {
+    if (millisecondsSinceEpoch.abs() > _maxMillisecondsSinceEpoch ||
+        (millisecondsSinceEpoch.abs() == _maxMillisecondsSinceEpoch &&
+            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.
     checkNotNullable(isUtc, "isUtc");
-
-    return millisecondsSinceEpoch;
   }
 
   /// Whether [other] is a [DateTime] at the same moment and in the
@@ -446,8 +436,6 @@
   /// independently of their zones.
   external bool operator ==(Object other);
 
-  external int get hashCode;
-
   /// Whether this [DateTime] occurs before [other].
   ///
   /// The comparison is independent
@@ -528,6 +516,8 @@
   /// ```
   external int compareTo(DateTime other);
 
+  int get hashCode => (_value ^ (_value >> 30)) & 0x3FFFFFFF;
+
   /// Returns this DateTime value in the local time zone.
   ///
   /// Returns this [DateTime] if it is already in the local time zone.
@@ -539,7 +529,7 @@
   /// ```
   DateTime toLocal() {
     if (isUtc) {
-      return _withUtc(isUtc: false);
+      return DateTime._withValue(_value, isUtc: false);
     }
     return this;
   }
@@ -555,11 +545,9 @@
   /// ```
   DateTime toUtc() {
     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) {
     int absN = n.abs();
     String sign = n < 0 ? "-" : "";
@@ -724,10 +712,18 @@
 
   external DateTime._now();
 
-  /// Returns the [DateTime] corresponding to the given components, or `null` if
-  /// the values are out of range.
-  external static DateTime? _finishParse(int year, int month, int day, int hour,
-      int minute, int second, int millisecond, int microsecond, bool isUtc);
+  /// Returns the time as value (millisecond or microsecond since epoch), or
+  /// null if the values are out of range.
+  external static int? _brokenDownDateToValue(
+      int year,
+      int month,
+      int day,
+      int hour,
+      int minute,
+      int second,
+      int millisecond,
+      int microsecond,
+      bool isUtc);
 
   /// The number of milliseconds since
   /// the "Unix epoch" 1970-01-01T00:00:00Z (UTC).
@@ -748,10 +744,8 @@
   /// 8,640,000,000,000,000,000us (100,000,000 days) from the Unix epoch.
   /// In other words: `microsecondsSinceEpoch.abs() <= 8640000000000000000`.
   ///
-  /// Note that this value does not always fit into 53 bits (the size of a IEEE
-  /// double).  On the web JavaScript platforms, there may be a rounding error
-  /// for DateTime values sufficiently far from the epoch. The year range close
-  /// to the epoch to avoid rounding is approximately 1685..2254.
+  /// Note that this value does not fit into 53 bits (the size of a IEEE double).
+  /// A JavaScript number is not able to hold this value.
   external int get microsecondsSinceEpoch;
 
   /// The time zone name.
diff --git a/sdk/lib/libraries.json b/sdk/lib/libraries.json
index a00925f..56265a2 100644
--- a/sdk/lib/libraries.json
+++ b/sdk/lib/libraries.json
@@ -390,10 +390,7 @@
       },
       "core": {
         "uri": "core/core.dart",
-        "patches": [
-          "_internal/js_shared/lib/date_time_patch.dart",
-          "_internal/js_runtime/lib/core_patch.dart"
-        ]
+        "patches": "_internal/js_runtime/lib/core_patch.dart"
       },
       "developer": {
         "uri": "developer/developer.dart",
@@ -573,10 +570,7 @@
       },
       "core": {
         "uri": "core/core.dart",
-        "patches": [
-          "_internal/js_shared/lib/date_time_patch.dart",
-          "_internal/js_dev_runtime/patch/core_patch.dart"
-        ]
+        "patches": "_internal/js_dev_runtime/patch/core_patch.dart"
       },
       "developer": {
         "uri": "developer/developer.dart",
diff --git a/sdk/lib/libraries.yaml b/sdk/lib/libraries.yaml
index e843722c..068e1b2 100644
--- a/sdk/lib/libraries.yaml
+++ b/sdk/lib/libraries.yaml
@@ -319,9 +319,7 @@
 
     core:
       uri: "core/core.dart"
-      patches:
-        - "_internal/js_shared/lib/date_time_patch.dart"
-        - "_internal/js_runtime/lib/core_patch.dart"
+      patches: "_internal/js_runtime/lib/core_patch.dart"
 
     developer:
       uri: "developer/developer.dart"
@@ -497,9 +495,7 @@
 
     core:
       uri: "core/core.dart"
-      patches:
-        - "_internal/js_shared/lib/date_time_patch.dart"
-        - "_internal/js_dev_runtime/patch/core_patch.dart"
+      patches: "_internal/js_dev_runtime/patch/core_patch.dart"
 
     developer:
       uri: "developer/developer.dart"
diff --git a/tests/corelib/date_time_extremes_test.dart b/tests/corelib/date_time_extremes_test.dart
index ad5316f..57facb1 100644
--- a/tests/corelib/date_time_extremes_test.dart
+++ b/tests/corelib/date_time_extremes_test.dart
@@ -7,13 +7,14 @@
 // Dart test program for DateTime, extreme values.
 
 bool get supportsMicroseconds =>
-    DateTime.fromMicrosecondsSinceEpoch(1).microsecondsSinceEpoch == 1;
+    new DateTime.fromMicrosecondsSinceEpoch(1).microsecondsSinceEpoch == 1;
 
 // Identical to _maxMillisecondsSinceEpoch in date_time.dart
 const int _MAX_MILLISECONDS = 8640000000000000;
 
 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(9, dt.month);
   Expect.equals(13, dt.day);
@@ -22,7 +23,7 @@
   Expect.equals(0, dt.second);
   Expect.equals(0, dt.millisecond);
   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(4, dt.month);
   Expect.equals(20, dt.day);
@@ -32,103 +33,71 @@
   Expect.equals(0, dt.millisecond);
   Expect.equals(0, dt.microsecond);
   // Make sure that we can build the extreme dates in local too.
-  dt = DateTime.fromMillisecondsSinceEpoch(_MAX_MILLISECONDS);
-  dt = DateTime(
+  dt = new DateTime.fromMillisecondsSinceEpoch(_MAX_MILLISECONDS);
+  dt = new DateTime(
       dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, dt.millisecond);
   Expect.equals(_MAX_MILLISECONDS, dt.millisecondsSinceEpoch);
-  dt = DateTime.fromMillisecondsSinceEpoch(-_MAX_MILLISECONDS);
-  dt = DateTime(
+  dt = new DateTime.fromMillisecondsSinceEpoch(-_MAX_MILLISECONDS);
+  dt = new DateTime(
       dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, dt.millisecond);
   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(() =>
-      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(() =>
-      DateTime.fromMillisecondsSinceEpoch(-_MAX_MILLISECONDS - 1, isUtc: true));
-  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));
+      new DateTime.utc(dt.year, dt.month, dt.day, dt.hour, dt.minute, 0, -1));
 
   if (!supportsMicroseconds) return;
 
-  /// The nearest value to [base] in the direction [delta]. For native `int`s,
-  /// this is just `base + delta`. For web `int`s outside the safe range, the
-  /// 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);
+  dt = new DateTime.fromMicrosecondsSinceEpoch(_MAX_MILLISECONDS * 1000);
+  dt = new DateTime(dt.year, dt.month, dt.day, dt.hour, dt.minute);
   Expect.equals(_MAX_MILLISECONDS * 1000, dt.microsecondsSinceEpoch);
-  print(-_MAX_MILLISECONDS * 1000);
-  dt = DateTime.fromMicrosecondsSinceEpoch(-_MAX_MILLISECONDS * 1000);
-  dt = DateTime(dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second);
+  dt = new DateTime.fromMicrosecondsSinceEpoch(-_MAX_MILLISECONDS * 1000);
+  dt = new DateTime(dt.year, dt.month, dt.day, dt.hour, dt.minute);
   Expect.equals(-_MAX_MILLISECONDS * 1000, dt.microsecondsSinceEpoch);
-  Expect.throws(() => DateTime.fromMicrosecondsSinceEpoch(
-      nearest(_MAX_MILLISECONDS * 1000, 1),
+  Expect.throws(() => new DateTime.fromMicrosecondsSinceEpoch(
+      _MAX_MILLISECONDS * 1000 + 1,
       isUtc: true));
-  Expect.throws(() => DateTime.fromMicrosecondsSinceEpoch(
-      nearest(-_MAX_MILLISECONDS * 1000, -1),
+  Expect.throws(() => new DateTime.fromMicrosecondsSinceEpoch(
+      -_MAX_MILLISECONDS * 1000 - 1,
       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(() =>
-      DateTime.utc(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('.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);
+      new DateTime.fromMicrosecondsSinceEpoch(_MAX_MILLISECONDS * 1000 + 1));
   Expect.throws(() =>
-      DateTime.utc(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('.000001Z'));
+      new DateTime.fromMicrosecondsSinceEpoch(-_MAX_MILLISECONDS * 1000 - 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));
+  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
   dt = DateTime.utc(1969, 12, 31, 23, 59, 59, 999, 999);
   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() {