Add a Zone-scoped clock field
diff --git a/lib/clock.dart b/lib/clock.dart
index 8915ff7..19d5efd 100644
--- a/lib/clock.dart
+++ b/lib/clock.dart
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 export 'src/clock.dart';
+export 'src/default.dart';
 
 /// Returns current time.
 @Deprecated("Pass around an instance of Clock instead.")
diff --git a/lib/src/clock.dart b/lib/src/clock.dart
index d11ed57..e518522 100644
--- a/lib/src/clock.dart
+++ b/lib/src/clock.dart
@@ -22,6 +22,10 @@
 /// (or [now()]) is defined by a function that returns a [DateTime]. By
 /// supplying your own time function or using [new Clock.fixed], you can control
 /// exactly what time a [Clock] returns and base your test expectations on that.
+///
+/// Most users should use the top-level [clock] field, which provides access to
+/// a default implementation of [Clock] which can be overridden using
+/// [withClock].
 class Clock {
   /// The function that's called to determine this clock's notion of the current
   /// time.
diff --git a/lib/src/default.dart b/lib/src/default.dart
new file mode 100644
index 0000000..b380927
--- /dev/null
+++ b/lib/src/default.dart
@@ -0,0 +1,48 @@
+// 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 'clock.dart';
+
+/// The key for the [Zone] value that controls the current implementation of
+/// [clock].
+final _clockKey = new Object();
+
+/// The key for the [Zone] value that controls whether nested zones can override
+/// [clock].
+final _isFinalKey = new Object();
+
+/// The default implementation of [clock] for the current [Zone].
+///
+/// This defaults to the system clock. It can be set within a zone using
+/// [withClock].
+Clock get clock => Zone.current[_clockKey] ?? const Clock();
+
+/// Runs [callback] with the given value for the top-level [clock] field.
+///
+/// This is [Zone]-scoped, so asynchronous callbacks spawned within [callback]
+/// will also use the new value for [clock].
+///
+/// If [isFinal] is `true`, calls to [withClock] within [callback] will throw a
+/// [StateError]. However, this parameter is deprecated and should be avoided.
+T withClock<T>(Clock clock, T callback(), {@deprecated bool isFinal: false}) {
+  if (Zone.current[_isFinalKey] ?? false) {
+    throw new StateError(
+        "Cannot call withClock() within a call to withClock(isFinal: true).");
+  }
+
+  return runZoned(callback,
+      zoneValues: {_clockKey: clock, _isFinalKey: isFinal});
+}
diff --git a/pubspec.yaml b/pubspec.yaml
index 5ebecf2..4d1449d 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -11,4 +11,4 @@
   meta: '>=0.9.0 <2.0.0'
 
 dev_dependencies:
-  test: '^0.12.0'
+  test: '^0.12.28'
diff --git a/test/clock_test.dart b/test/clock_test.dart
index 633cdb9..3d2d1b2 100644
--- a/test/clock_test.dart
+++ b/test/clock_test.dart
@@ -16,20 +16,12 @@
 
 import 'package:test/test.dart';
 
-/// A utility function for tersely constructing a [DateTime] with no time
-/// component.
-DateTime _date(int year, [int month, int day]) =>
-    new DateTime(year, month ?? 1, day ?? 1);
-
-/// Return a clock that always returns a date with the given [year], [month],
-/// and [day].
-Clock _fixed(int year, [int month, int day]) =>
-    new Clock.fixed(_date(year, month, day));
+import 'utils.dart';
 
 main() {
   Clock clock;
   setUp(() {
-    clock = new Clock.fixed(_date(2013));
+    clock = new Clock.fixed(date(2013));
   });
 
   test('should return a non-null value from system clock', () {
@@ -50,24 +42,24 @@
   });
 
   test('should return time provided by a custom function', () {
-    var time = _date(2013);
+    var time = date(2013);
     var fixedClock = new Clock(() => time);
-    expect(fixedClock.now(), _date(2013));
+    expect(fixedClock.now(), date(2013));
 
-    time = _date(2014);
-    expect(fixedClock.now(), _date(2014));
+    time = date(2014);
+    expect(fixedClock.now(), date(2014));
   });
 
   test('should return fixed time', () {
-    expect(new Clock.fixed(_date(2013)).now(), _date(2013));
+    expect(new Clock.fixed(date(2013)).now(), date(2013));
   });
 
   test('should return time Duration ago', () {
-    expect(clock.agoBy(const Duration(days: 366)), _date(2012));
+    expect(clock.agoBy(const Duration(days: 366)), date(2012));
   });
 
   test('should return time Duration from now', () {
-    expect(clock.fromNowBy(const Duration(days: 365)), _date(2014));
+    expect(clock.fromNowBy(const Duration(days: 365)), date(2014));
   });
 
   test('should return time parts ago', () {
@@ -135,86 +127,86 @@
   });
 
   test('should return time days ago', () {
-    expect(clock.daysAgo(10), _date(2012, 12, 22));
+    expect(clock.daysAgo(10), date(2012, 12, 22));
   });
 
   test('should return time days from now', () {
-    expect(clock.daysFromNow(3), _date(2013, 1, 4));
+    expect(clock.daysFromNow(3), date(2013, 1, 4));
   });
 
   test('should return time months ago on the same date', () {
-    expect(clock.monthsAgo(1), _date(2012, 12, 1));
-    expect(clock.monthsAgo(2), _date(2012, 11, 1));
-    expect(clock.monthsAgo(3), _date(2012, 10, 1));
-    expect(clock.monthsAgo(4), _date(2012, 9, 1));
+    expect(clock.monthsAgo(1), date(2012, 12, 1));
+    expect(clock.monthsAgo(2), date(2012, 11, 1));
+    expect(clock.monthsAgo(3), date(2012, 10, 1));
+    expect(clock.monthsAgo(4), date(2012, 9, 1));
   });
 
   test('should return time months from now on the same date', () {
-    expect(clock.monthsFromNow(1), _date(2013, 2, 1));
-    expect(clock.monthsFromNow(2), _date(2013, 3, 1));
-    expect(clock.monthsFromNow(3), _date(2013, 4, 1));
-    expect(clock.monthsFromNow(4), _date(2013, 5, 1));
+    expect(clock.monthsFromNow(1), date(2013, 2, 1));
+    expect(clock.monthsFromNow(2), date(2013, 3, 1));
+    expect(clock.monthsFromNow(3), date(2013, 4, 1));
+    expect(clock.monthsFromNow(4), date(2013, 5, 1));
   });
 
   test('should go from 2013-05-31 to 2012-11-30', () {
-    expect(_fixed(2013, 5, 31).monthsAgo(6), _date(2012, 11, 30));
+    expect(fixed(2013, 5, 31).monthsAgo(6), date(2012, 11, 30));
   });
 
   test('should go from 2013-03-31 to 2013-02-28 (common year)', () {
-    expect(_fixed(2013, 3, 31).monthsAgo(1), _date(2013, 2, 28));
+    expect(fixed(2013, 3, 31).monthsAgo(1), date(2013, 2, 28));
   });
 
   test('should go from 2013-05-31 to 2013-02-28 (common year)', () {
-    expect(_fixed(2013, 5, 31).monthsAgo(3), _date(2013, 2, 28));
+    expect(fixed(2013, 5, 31).monthsAgo(3), date(2013, 2, 28));
   });
 
   test('should go from 2004-03-31 to 2004-02-29 (leap year)', () {
-    expect(_fixed(2004, 3, 31).monthsAgo(1), _date(2004, 2, 29));
+    expect(fixed(2004, 3, 31).monthsAgo(1), date(2004, 2, 29));
   });
 
   test('should go from 2013-03-31 to 2013-06-30', () {
-    expect(_fixed(2013, 3, 31).monthsFromNow(3), _date(2013, 6, 30));
+    expect(fixed(2013, 3, 31).monthsFromNow(3), date(2013, 6, 30));
   });
 
   test('should go from 2003-12-31 to 2004-02-29 (common to leap)', () {
-    expect(_fixed(2003, 12, 31).monthsFromNow(2), _date(2004, 2, 29));
+    expect(fixed(2003, 12, 31).monthsFromNow(2), date(2004, 2, 29));
   });
 
   test('should go from 2004-02-29 to 2003-02-28 by year', () {
-    expect(_fixed(2004, 2, 29).yearsAgo(1), _date(2003, 2, 28));
+    expect(fixed(2004, 2, 29).yearsAgo(1), date(2003, 2, 28));
   });
 
   test('should go from 2004-02-29 to 2003-02-28 by month', () {
-    expect(_fixed(2004, 2, 29).monthsAgo(12), _date(2003, 2, 28));
+    expect(fixed(2004, 2, 29).monthsAgo(12), date(2003, 2, 28));
   });
 
   test('should go from 2004-02-29 to 2005-02-28 by year', () {
-    expect(_fixed(2004, 2, 29).yearsFromNow(1), _date(2005, 2, 28));
+    expect(fixed(2004, 2, 29).yearsFromNow(1), date(2005, 2, 28));
   });
 
   test('should go from 2004-02-29 to 2005-02-28 by month', () {
-    expect(_fixed(2004, 2, 29).monthsFromNow(12), _date(2005, 2, 28));
+    expect(fixed(2004, 2, 29).monthsFromNow(12), date(2005, 2, 28));
   });
 
   test('should return time years ago on the same date', () {
-    expect(clock.yearsAgo(1), _date(2012, 1, 1)); // leap year
-    expect(clock.yearsAgo(2), _date(2011, 1, 1));
-    expect(clock.yearsAgo(3), _date(2010, 1, 1));
-    expect(clock.yearsAgo(4), _date(2009, 1, 1));
-    expect(clock.yearsAgo(5), _date(2008, 1, 1)); // leap year
-    expect(clock.yearsAgo(6), _date(2007, 1, 1));
-    expect(clock.yearsAgo(30), _date(1983, 1, 1));
-    expect(clock.yearsAgo(2013), _date(0, 1, 1));
+    expect(clock.yearsAgo(1), date(2012, 1, 1)); // leap year
+    expect(clock.yearsAgo(2), date(2011, 1, 1));
+    expect(clock.yearsAgo(3), date(2010, 1, 1));
+    expect(clock.yearsAgo(4), date(2009, 1, 1));
+    expect(clock.yearsAgo(5), date(2008, 1, 1)); // leap year
+    expect(clock.yearsAgo(6), date(2007, 1, 1));
+    expect(clock.yearsAgo(30), date(1983, 1, 1));
+    expect(clock.yearsAgo(2013), date(0, 1, 1));
   });
 
   test('should return time years from now on the same date', () {
-    expect(clock.yearsFromNow(1), _date(2014, 1, 1));
-    expect(clock.yearsFromNow(2), _date(2015, 1, 1));
-    expect(clock.yearsFromNow(3), _date(2016, 1, 1));
-    expect(clock.yearsFromNow(4), _date(2017, 1, 1));
-    expect(clock.yearsFromNow(5), _date(2018, 1, 1));
-    expect(clock.yearsFromNow(6), _date(2019, 1, 1));
-    expect(clock.yearsFromNow(30), _date(2043, 1, 1));
-    expect(clock.yearsFromNow(1000), _date(3013, 1, 1));
+    expect(clock.yearsFromNow(1), date(2014, 1, 1));
+    expect(clock.yearsFromNow(2), date(2015, 1, 1));
+    expect(clock.yearsFromNow(3), date(2016, 1, 1));
+    expect(clock.yearsFromNow(4), date(2017, 1, 1));
+    expect(clock.yearsFromNow(5), date(2018, 1, 1));
+    expect(clock.yearsFromNow(6), date(2019, 1, 1));
+    expect(clock.yearsFromNow(30), date(2043, 1, 1));
+    expect(clock.yearsFromNow(1000), date(3013, 1, 1));
   });
 }
diff --git a/test/default_test.dart b/test/default_test.dart
new file mode 100644
index 0000000..edcb7cd
--- /dev/null
+++ b/test/default_test.dart
@@ -0,0 +1,79 @@
+// 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("the default clock returns the system time", () {
+    expect(new DateTime.now().difference(clock.now()).inMilliseconds.abs(),
+        lessThan(100));
+  });
+
+  group("withClock()", () {
+    group("overrides the clock", () {
+      test("synchronously", () {
+        var time = date(1990, 11, 8);
+        withClock(new Clock(() => time), () {
+          expect(clock.now(), equals(time));
+          time = date(2016, 6, 26);
+          expect(clock.now(), equals(time));
+        });
+      });
+
+      test("asynchronously", () {
+        var time = date(1990, 11, 8);
+        withClock(new Clock.fixed(time), () {
+          expect(new Future(() async {
+            expect(clock.now(), equals(time));
+          }), completes);
+        });
+      });
+
+      test("within another withClock() call", () {
+        var outerTime = date(1990, 11, 8);
+        withClock(new Clock.fixed(outerTime), () {
+          expect(clock.now(), equals(outerTime));
+
+          var innerTime = date(2016, 11, 8);
+          withClock(new Clock.fixed(innerTime), () {
+            expect(clock.now(), equals(innerTime));
+            expect(new Future(() async {
+              expect(clock.now(), equals(innerTime));
+            }), completes);
+          });
+
+          expect(clock.now(), equals(outerTime));
+        });
+      });
+    });
+
+    test("with isFinal: true doesn't allow nested calls", () {
+      var outerTime = date(1990, 11, 8);
+      withClock(new Clock.fixed(outerTime), () {
+        expect(clock.now(), equals(outerTime));
+
+        expect(
+            () => withClock(fixed(2016, 11, 8), neverCalled), throwsStateError);
+
+        expect(clock.now(), equals(outerTime));
+      }, isFinal: true);
+    });
+  });
+}
diff --git a/test/utils.dart b/test/utils.dart
new file mode 100644
index 0000000..17c07f3
--- /dev/null
+++ b/test/utils.dart
@@ -0,0 +1,25 @@
+// 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 'package:clock/clock.dart';
+
+/// A utility function for tersely constructing a [DateTime] with no time
+/// component.
+DateTime date(int year, [int month, int day]) =>
+    new DateTime(year, month ?? 1, day ?? 1);
+
+/// Returns a clock that always returns a date with the given [year], [month],
+/// and [day].
+Clock fixed(int year, [int month, int day]) =>
+    new Clock.fixed(date(year, month, day));