Add features from the old clock package where possible
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5b26ad3..4ad290f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,33 @@
 ## 1.0.0
 
-* Initial version.
+This release contains the `Clock` class that was defined in [`quiver`][]. It's
+backwards-compatible with the `quiver` version, and *mostly*
+backwards-compatible with the old version of the `clock` package.
+
+[`quiver`]: https://pub.dartlang.org/packages/quiver
+
+### New Features
+
+* A top-level `clock` field has been added that provides a default `Clock`
+  implementation. It can be controlled by the `withClock()` function. It should
+  generally be used in preference to manual dependency-injection, since it will
+  work with the [`fake_async`][] package.
+
+* A `Clock.stopwatch()` method has been added that creates a `Stopwatch` that
+  uses the clock as its source of time.
+
+[`fake_async`]: https://pub.dartlang.org/packages/fake_async
+
+### Changes Relative to `clock` 0.1
+
+* The top-level `new` getter and `getStopwatch()` methods are deprecated.
+  `clock.new()` and `clock.getStopwatch()` should be used instead.
+
+* `Clock.getStopwatch()` is deprecated. `Clock.stopwatch()` should be used instead.
+
+* The `isFinal` argument to `withClock()` is deprecated.
+
+* `new Clock()` now takes an optional positional argument that returns the
+  current time as a `DateTime` instead of its old arguments.
+
+* `Clock.now()` is now a method rather than a getter.
diff --git a/README.md b/README.md
index 905f3b3..68bdba1 100644
--- a/README.md
+++ b/README.md
@@ -15,7 +15,7 @@
 
 /// Runs [callback] and prints how long it took.
 T runWithTiming<T>(T callback()) {
-  var stopwatch = clock.getStopwatch()..start();
+  var stopwatch = clock.stopwatch()..start();
   var result = callback();
   print("It took ${stopwatch.elapsed}!");
   return result;
diff --git a/lib/clock.dart b/lib/clock.dart
index 19d5efd..786585f 100644
--- a/lib/clock.dart
+++ b/lib/clock.dart
@@ -19,6 +19,14 @@
 @Deprecated("Pass around an instance of Clock instead.")
 typedef DateTime TimeFunction();
 
-/// Return current system time.
+/// Returns the current system time.
 @Deprecated("Use new DateTime.now() instead.")
 DateTime systemTime() => new DateTime.now();
+
+/// Returns the current time as reported by [clock].
+@Deprecated("Use clock.now() instead.")
+DateTime get now => clock.now();
+
+/// Returns a stopwatch that uses the current time as reported by [clock].
+@Deprecated("Use clock.stopwatch() instead.")
+Stopwatch getStopwatch() => clock.stopwatch();
diff --git a/lib/src/clock.dart b/lib/src/clock.dart
index e518522..0ff29bf 100644
--- a/lib/src/clock.dart
+++ b/lib/src/clock.dart
@@ -15,6 +15,7 @@
 import 'utils.dart';
 
 import '../clock.dart';
+import 'stopwatch.dart';
 
 /// A provider for the "current time" and points relative to the current time.
 ///
@@ -170,4 +171,11 @@
   /// If the current day of the month isn't valid in the new year, the nearest
   /// valid day in the original month will be used.
   DateTime yearsFromNow(int years) => yearsAgo(-years);
+
+  /// Returns a new stopwatch that uses the current time as reported by [this].
+  Stopwatch stopwatch() => new ClockStopwatch(this);
+
+  /// Returns a new stopwatch that uses the current time as reported by [this].
+  @Deprecated("Use stopwatch() instead.")
+  Stopwatch getStopwatch() => stopwatch();
 }
diff --git a/lib/src/stopwatch.dart b/lib/src/stopwatch.dart
new file mode 100644
index 0000000..1cf66a4
--- /dev/null
+++ b/lib/src/stopwatch.dart
@@ -0,0 +1,64 @@
+// Copyright 2018 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import 'clock.dart';
+
+/// The system's timer frequency in Hz.
+///
+/// We can't really know how frequently the clock is updated, and that may not
+/// even make sense for some implementations, so we just pretend we follow the
+/// system's frequency.
+final _frequency = new Stopwatch().frequency;
+
+/// A stopwatch that gets its notion of the current time from a [Clock].
+class ClockStopwatch implements Stopwatch {
+  /// The provider for this stopwatch's notion of the current time.
+  final Clock _clock;
+
+  /// The number of elapsed microseconds that have been recorded from previous
+  /// runs of this stopwatch.
+  ///
+  /// This doesn't include the time between [_start] and the current time.
+  var _elapsed = 0;
+
+  /// The point at which [start] was called most recently, or `null` if this
+  /// isn't active.
+  DateTime _start;
+
+  ClockStopwatch(this._clock);
+
+  int get frequency => _frequency;
+  int get elapsedTicks => (elapsedMicroseconds * frequency) ~/ 1000000;
+  Duration get elapsed => new Duration(microseconds: elapsedMicroseconds);
+  int get elapsedMilliseconds => elapsedMicroseconds ~/ 1000;
+  bool get isRunning => _start != null;
+
+  int get elapsedMicroseconds =>
+      _elapsed +
+      (_start == null ? 0 : _clock.now().difference(_start).inMicroseconds);
+
+  void start() {
+    _start ??= _clock.now();
+  }
+
+  void stop() {
+    _elapsed = elapsedMicroseconds;
+    _start = null;
+  }
+
+  void reset() {
+    _elapsed = 0;
+    if (_start != null) _start = _clock.now();
+  }
+}
diff --git a/pubspec.yaml b/pubspec.yaml
index 4d1449d..8a79678 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
 name: clock
-version: 1.0.0-dev
+version: 1.0.0
 description: A fakeable wrapper for dart:core clock APIs
 author: Dart Team <misc@dartlang.org>
 homepage: https://github.com/dart-lang/clock
diff --git a/test/stopwatch_test.dart b/test/stopwatch_test.dart
new file mode 100644
index 0000000..66f01b0
--- /dev/null
+++ b/test/stopwatch_test.dart
@@ -0,0 +1,169 @@
+// Copyright 2018 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the 'License');
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an 'AS IS' BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import 'dart:async';
+
+import 'package:clock/clock.dart';
+
+import 'package:test/test.dart';
+
+import 'utils.dart';
+
+void main() {
+  test("returns the system frequency", () {
+    expect(fixed(1990, 11, 8).stopwatch().frequency,
+        equals(new Stopwatch().frequency));
+  });
+
+  group("before it starts", () {
+    Stopwatch stopwatch;
+    setUp(() {
+      stopwatch = clock.stopwatch();
+    });
+
+    test("is not running", () => expect(stopwatch.isRunning, isFalse));
+
+    test("stop() does nothing", () {
+      stopwatch.stop();
+      expect(stopwatch.isRunning, isFalse);
+      expect(stopwatch.elapsed, equals(Duration.ZERO));
+    });
+
+    group("reports no elapsed", () {
+      test("duration", () => expect(stopwatch.elapsed, equals(Duration.ZERO)));
+      test("ticks", () => expect(stopwatch.elapsedTicks, isZero));
+      test("microseconds", () => expect(stopwatch.elapsedMicroseconds, isZero));
+      test("milliseconds", () => expect(stopwatch.elapsedMilliseconds, isZero));
+    });
+  });
+
+  group("when 12345μs have elapsed", () {
+    DateTime time;
+    Clock clock;
+    Stopwatch stopwatch;
+    setUp(() {
+      time = date(1990, 11, 8);
+      clock = new Clock(() => time);
+      stopwatch = clock.stopwatch()..start();
+      time = clock.microsFromNow(12345);
+    });
+
+    group("and the stopwatch is active", () {
+      test("is running", () {
+        expect(stopwatch.isRunning, isTrue);
+      });
+
+      test("reports more elapsed time", () {
+        time = clock.microsFromNow(54321);
+        expect(stopwatch.elapsedMicroseconds, equals(66666));
+      });
+
+      test("start does nothing", () {
+        stopwatch.start();
+        expect(stopwatch.isRunning, isTrue);
+        expect(stopwatch.elapsedMicroseconds, equals(12345));
+      });
+
+      group("reset()", () {
+        setUp(() {
+          stopwatch.reset();
+        });
+
+        test("sets the elapsed time to zero", () {
+          expect(stopwatch.elapsed, equals(Duration.ZERO));
+        });
+
+        test("reports more elapsed time", () {
+          time = clock.microsFromNow(54321);
+          expect(stopwatch.elapsedMicroseconds, equals(54321));
+        });
+      });
+
+      group("reports elapsed", () {
+        test("duration", () {
+          expect(stopwatch.elapsed, equals(new Duration(microseconds: 12345)));
+        });
+
+        test("ticks", () {
+          expect(stopwatch.elapsedTicks,
+              equals((new Stopwatch().frequency * 12345) ~/ 1000000));
+        });
+
+        test("microseconds", () {
+          expect(stopwatch.elapsedMicroseconds, equals(12345));
+        });
+
+        test("milliseconds", () {
+          expect(stopwatch.elapsedMilliseconds, equals(12));
+        });
+      });
+    });
+
+    group("and the stopwatch is inactive, reports that as", () {
+      setUp(() {
+        stopwatch.stop();
+      });
+
+      test("is not running", () {
+        expect(stopwatch.isRunning, isFalse);
+      });
+
+      test("doesn't report more elapsed time", () {
+        time = clock.microsFromNow(54321);
+        expect(stopwatch.elapsedMicroseconds, equals(12345));
+      });
+
+      test("start starts reporting more elapsed time", () {
+        stopwatch.start();
+        expect(stopwatch.isRunning, isTrue);
+        time = clock.microsFromNow(54321);
+        expect(stopwatch.elapsedMicroseconds, equals(66666));
+      });
+
+      group("reset()", () {
+        setUp(() {
+          stopwatch.reset();
+        });
+
+        test("sets the elapsed time to zero", () {
+          expect(stopwatch.elapsed, equals(Duration.ZERO));
+        });
+
+        test("doesn't report more elapsed time", () {
+          time = clock.microsFromNow(54321);
+          expect(stopwatch.elapsed, equals(Duration.ZERO));
+        });
+      });
+
+      group("reports elapsed", () {
+        test("duration", () {
+          expect(stopwatch.elapsed, equals(new Duration(microseconds: 12345)));
+        });
+
+        test("ticks", () {
+          expect(stopwatch.elapsedTicks,
+              equals((new Stopwatch().frequency * 12345) ~/ 1000000));
+        });
+
+        test("microseconds", () {
+          expect(stopwatch.elapsedMicroseconds, equals(12345));
+        });
+
+        test("milliseconds", () {
+          expect(stopwatch.elapsedMilliseconds, equals(12));
+        });
+      });
+    });
+  });
+}