Upgraded the rest of Time.

Change-Id: I0ee083837e51d8f74a798b7ba14a3b6bb3859f35
diff --git a/aos/common/actions/action_test.cc b/aos/common/actions/action_test.cc
index 21da2c7..1538d03 100644
--- a/aos/common/actions/action_test.cc
+++ b/aos/common/actions/action_test.cc
@@ -2,6 +2,7 @@
 
 #include <memory>
 #include <thread>
+#include <chrono>
 
 #include "gtest/gtest.h"
 
@@ -13,13 +14,14 @@
 #include "aos/common/event.h"
 #include "aos/testing/test_shm.h"
 
-using ::aos::time::Time;
-
 namespace aos {
 namespace common {
 namespace actions {
 namespace testing {
 
+
+namespace chrono = ::std::chrono;
+
 class TestActorIndex
     : public aos::common::actions::ActorBase<actions::TestActionQueueGroup> {
  public:
@@ -135,7 +137,7 @@
 
   ASSERT_FALSE(actions::test_action.status.FetchLatest());
   ::std::thread init_thread([&nop_act]() { nop_act.Initialize(); });
-  ::aos::time::SleepFor(::aos::time::Time::InSeconds(0.1));
+  ::std::this_thread::sleep_for(chrono::milliseconds(100));
   ASSERT_TRUE(actions::test_action.goal.MakeWithBuilder().run(1).Send());
   init_thread.join();
   ASSERT_TRUE(actions::test_action.status.FetchLatest());
diff --git a/aos/common/actions/actor.h b/aos/common/actions/actor.h
index 5d0c70d..d2d05fc 100644
--- a/aos/common/actions/actor.h
+++ b/aos/common/actions/actor.h
@@ -4,12 +4,13 @@
 #include <stdio.h>
 #include <inttypes.h>
 
+#include <chrono>
 #include <functional>
 
+#include "aos/common/controls/control_loop.h"
 #include "aos/common/logging/logging.h"
 #include "aos/common/logging/queue_logging.h"
 #include "aos/common/time.h"
-#include "aos/common/controls/control_loop.h"
 #include "aos/common/util/phased_loop.h"
 
 namespace aos {
@@ -65,13 +66,14 @@
   // Returns false if the action was canceled or failed, and true if the wait
   // succeeded.
   bool WaitOrCancel(monotonic_clock::duration duration) {
-    return !WaitUntil([]() {
-      ::aos::time::PhasedLoopXMS(
-          ::std::chrono::duration_cast<::std::chrono::milliseconds>(
-              ::aos::controls::kLoopFrequency).count(),
-          2500);
-      return false;
-    }, ::aos::monotonic_clock::now() + duration);
+    ::aos::time::PhasedLoop phased_loop(::aos::controls::kLoopFrequency,
+                                        ::std::chrono::milliseconds(5) / 2);
+    return !WaitUntil(
+        [&phased_loop]() {
+          phased_loop.SleepUntilNext();
+          return false;
+        },
+        ::aos::monotonic_clock::now() + duration);
   }
 
   // Returns true if the action should be canceled.
diff --git a/aos/common/condition_test.cc b/aos/common/condition_test.cc
index 0e7bfe4..f8e4e65 100644
--- a/aos/common/condition_test.cc
+++ b/aos/common/condition_test.cc
@@ -5,6 +5,7 @@
 #include <sys/wait.h>
 
 #include <atomic>
+#include <chrono>
 #include <thread>
 
 #include "gtest/gtest.h"
@@ -21,18 +22,16 @@
 #include "aos/common/util/thread.h"
 #include "aos/testing/prevent_exit.h"
 
-using ::aos::time::Time;
-
 namespace aos {
 namespace testing {
 
+namespace chrono = ::std::chrono;
+
 class ConditionTestCommon : public ::testing::Test {
  public:
   ConditionTestCommon() {}
 
-  void Settle() {
-    time::SleepFor(::Time::InSeconds(0.008));
-  }
+  void Settle() { ::std::this_thread::sleep_for(chrono::milliseconds(8)); }
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ConditionTestCommon);
@@ -132,16 +131,22 @@
   };
 
   // This amount gets added to any passed in delay to make the test repeatable.
-  static constexpr ::Time kMinimumDelay = ::Time::InSeconds(0.15);
-  static constexpr ::Time kDefaultTimeout = ::Time::InSeconds(0.15);
+  static constexpr chrono::milliseconds kMinimumDelay =
+      chrono::milliseconds(150);
+  static constexpr chrono::milliseconds kDefaultTimeout =
+      chrono::milliseconds(150);
 
   // delay is how long to wait before doing action to condition.
   // timeout is how long to wait after delay before deciding that it's hung.
-  ConditionTestProcess(const ::Time &delay, Action action, Condition *condition,
-                       const ::Time &timeout = kDefaultTimeout)
-    : delay_(kMinimumDelay + delay), action_(action), condition_(condition),
-      timeout_(delay_ + timeout), child_(-1),
-      shared_(static_cast<Shared *>(shm_malloc(sizeof(Shared)))) {
+  ConditionTestProcess(chrono::milliseconds delay, Action action,
+                       Condition *condition,
+                       chrono::milliseconds timeout = kDefaultTimeout)
+      : delay_(kMinimumDelay + delay),
+        action_(action),
+        condition_(condition),
+        timeout_(delay_ + timeout),
+        child_(-1),
+        shared_(static_cast<Shared *>(shm_malloc(sizeof(Shared)))) {
     new (shared_) Shared();
   }
   ~ConditionTestProcess() {
@@ -179,15 +184,17 @@
       return ::testing::AssertionFailure() << "already returned";
     }
     if (shared_->delayed) {
-      if (shared_->start_time > ::Time::Now() + timeout_) {
+      if (shared_->start_time > monotonic_clock::now() + timeout_) {
         Kill();
         return ::testing::AssertionSuccess() << "already been too long";
       }
     } else {
       CHECK_EQ(0, futex_wait(&shared_->done_delaying));
     }
-    time::SleepFor(::Time::InSeconds(0.01));
-    if (!shared_->finished) time::SleepUntil(shared_->start_time + timeout_);
+    ::std::this_thread::sleep_for(chrono::milliseconds(10));
+    if (!shared_->finished) {
+      ::std::this_thread::sleep_until(shared_->start_time + timeout_);
+    }
     if (shared_->finished) {
       Join();
       return ::testing::AssertionFailure() << "completed within timeout";
@@ -204,14 +211,17 @@
  private:
   struct Shared {
     Shared()
-      : started(false), delayed(false), done_delaying(0), start_time(0, 0),
-        finished(false), ready(0) {
-    }
+        : started(false),
+          delayed(false),
+          done_delaying(0),
+          start_time(monotonic_clock::epoch()),
+          finished(false),
+          ready(0) {}
 
     volatile bool started;
     volatile bool delayed;
     aos_futex done_delaying;
-    ::Time start_time;
+    monotonic_clock::time_point start_time;
     volatile bool finished;
     aos_futex ready;
   };
@@ -223,8 +233,8 @@
       ASSERT_EQ(1, futex_set(&shared_->ready));
       ASSERT_FALSE(condition_->m()->Lock());
     }
-    time::SleepFor(delay_);
-    shared_->start_time = ::Time::Now();
+    ::std::this_thread::sleep_for(delay_);
+    shared_->start_time = monotonic_clock::now();
     shared_->delayed = true;
     ASSERT_NE(-1, futex_set(&shared_->done_delaying));
     if (action_ != Action::kWaitLockStart) {
@@ -253,10 +263,10 @@
     Join();
   }
 
-  const ::Time delay_;
+  const chrono::milliseconds delay_;
   const Action action_;
   Condition *const condition_;
-  const ::Time timeout_;
+  const chrono::milliseconds timeout_;
 
   pid_t child_;
 
@@ -264,13 +274,13 @@
 
   DISALLOW_COPY_AND_ASSIGN(ConditionTestProcess);
 };
-constexpr ::Time ConditionTestProcess::kMinimumDelay;
-constexpr ::Time ConditionTestProcess::kDefaultTimeout;
+constexpr chrono::milliseconds ConditionTestProcess::kMinimumDelay;
+constexpr chrono::milliseconds ConditionTestProcess::kDefaultTimeout;
 
 // Makes sure that the testing framework and everything work for a really simple
 // Wait() and then Signal().
 TEST_F(ConditionTest, Basic) {
-  ConditionTestProcess child(::Time(0, 0),
+  ConditionTestProcess child(chrono::milliseconds(0),
                              ConditionTestProcess::Action::kWait,
                              &shared_->condition);
   child.Start();
@@ -282,7 +292,7 @@
 
 // Makes sure that the worker child locks before it tries to Wait() etc.
 TEST_F(ConditionTest, Locking) {
-  ConditionTestProcess child(::Time(0, 0),
+  ConditionTestProcess child(chrono::milliseconds(0),
                              ConditionTestProcess::Action::kWait,
                              &shared_->condition);
   ASSERT_FALSE(shared_->mutex.Lock());
@@ -299,7 +309,7 @@
 // Tests that the work child only catches a Signal() after the mutex gets
 // unlocked.
 TEST_F(ConditionTest, LockFirst) {
-  ConditionTestProcess child(::Time(0, 0),
+  ConditionTestProcess child(chrono::milliseconds(0),
                              ConditionTestProcess::Action::kWait,
                              &shared_->condition);
   ASSERT_FALSE(shared_->mutex.Lock());
@@ -317,7 +327,7 @@
 
 // Tests that the mutex gets relocked after Wait() returns.
 TEST_F(ConditionTest, Relocking) {
-  ConditionTestProcess child(::Time(0, 0),
+  ConditionTestProcess child(chrono::milliseconds(0),
                              ConditionTestProcess::Action::kWaitNoUnlock,
                              &shared_->condition);
   child.Start();
@@ -330,13 +340,13 @@
 
 // Tests that Signal() stops exactly 1 Wait()er.
 TEST_F(ConditionTest, SignalOne) {
-  ConditionTestProcess child1(::Time(0, 0),
+  ConditionTestProcess child1(chrono::milliseconds(0),
                               ConditionTestProcess::Action::kWait,
                               &shared_->condition);
-  ConditionTestProcess child2(::Time(0, 0),
+  ConditionTestProcess child2(chrono::milliseconds(0),
                               ConditionTestProcess::Action::kWait,
                               &shared_->condition);
-  ConditionTestProcess child3(::Time(0, 0),
+  ConditionTestProcess child3(chrono::milliseconds(0),
                               ConditionTestProcess::Action::kWait,
                               &shared_->condition);
   auto number_finished = [&]() { return (child1.IsFinished() ? 1 : 0) +
@@ -362,13 +372,13 @@
 
 // Tests that Brodcast() wakes multiple Wait()ers.
 TEST_F(ConditionTest, Broadcast) {
-  ConditionTestProcess child1(::Time(0, 0),
+  ConditionTestProcess child1(chrono::milliseconds(0),
                               ConditionTestProcess::Action::kWait,
                               &shared_->condition);
-  ConditionTestProcess child2(::Time(0, 0),
+  ConditionTestProcess child2(chrono::milliseconds(0),
                               ConditionTestProcess::Action::kWait,
                               &shared_->condition);
-  ConditionTestProcess child3(::Time(0, 0),
+  ConditionTestProcess child3(chrono::milliseconds(0),
                               ConditionTestProcess::Action::kWait,
                               &shared_->condition);
   child1.Start();
diff --git a/aos/common/controls/control_loop-tmpl.h b/aos/common/controls/control_loop-tmpl.h
index 81b5d20..474c5ce 100644
--- a/aos/common/controls/control_loop-tmpl.h
+++ b/aos/common/controls/control_loop-tmpl.h
@@ -63,8 +63,7 @@
       // If the driver's station reports being disabled, we're probably not
       // actually going to send motor values regardless of what the FPGA
       // reports.
-      last_pwm_sent_ = monotonic_clock::time_point(
-          ::std::chrono::nanoseconds(::aos::robot_state->sent_time.ToNSec()));
+      last_pwm_sent_ = ::aos::robot_state->sent_time;
     }
   }
 
diff --git a/aos/common/event.cc b/aos/common/event.cc
index af9c9c5..ffb62b4 100644
--- a/aos/common/event.cc
+++ b/aos/common/event.cc
@@ -1,5 +1,7 @@
 #include "aos/common/event.h"
 
+#include <chrono>
+
 #include "aos/common/type_traits.h"
 #include "aos/common/logging/logging.h"
 
@@ -20,8 +22,14 @@
   }
 }
 
-bool Event::WaitTimeout(const ::aos::time::Time &timeout) {
-  const auto timeout_timespec = timeout.ToTimespec();
+bool Event::WaitTimeout(monotonic_clock::duration timeout) {
+  ::std::chrono::seconds sec =
+      ::std::chrono::duration_cast<::std::chrono::seconds>(timeout);
+  ::std::chrono::nanoseconds nsec =
+      ::std::chrono::duration_cast<::std::chrono::nanoseconds>(timeout - sec);
+  struct timespec timeout_timespec;
+  timeout_timespec.tv_sec = sec.count();
+  timeout_timespec.tv_nsec = nsec.count();
   while (true) {
     if (__atomic_load_n(&impl_, __ATOMIC_SEQ_CST) != 0) {
       return true;
diff --git a/aos/common/event.h b/aos/common/event.h
index b3ee87b..559aad5 100644
--- a/aos/common/event.h
+++ b/aos/common/event.h
@@ -42,7 +42,7 @@
   // Waits for the event to be set or until timeout has elapsed. Returns
   // immediately if it is already set.
   // Returns true if the event was Set or false if the timeout expired.
-  bool WaitTimeout(const ::aos::time::Time &timeout);
+  bool WaitTimeout(monotonic_clock::duration timeout);
 
   // Wakes up all Wait()ers and sets the event (atomically).
   void Set();
diff --git a/aos/common/event_test.cc b/aos/common/event_test.cc
index 91af403..764dd49 100644
--- a/aos/common/event_test.cc
+++ b/aos/common/event_test.cc
@@ -1,15 +1,19 @@
 #include "aos/common/event.h"
 
+#include <chrono>
 #include <thread>
 
 #include "gtest/gtest.h"
 
-#include "aos/testing/test_logging.h"
 #include "aos/common/time.h"
+#include "aos/testing/test_logging.h"
 
 namespace aos {
 namespace testing {
 
+namespace chrono = ::std::chrono;
+namespace this_thread = ::std::this_thread;
+
 class EventTest : public ::testing::Test {
  public:
   Event test_event_;
@@ -50,38 +54,38 @@
 
 // Tests that an event blocks correctly.
 TEST_F(EventTest, Blocks) {
-  time::Time start_time, finish_time;
+  monotonic_clock::time_point start_time, finish_time;
   // Without this, it sometimes manages to fail under tsan.
   Event started;
   ::std::thread thread([this, &start_time, &finish_time, &started]() {
-    start_time = time::Time::Now();
+    start_time = monotonic_clock::now();
     started.Set();
     test_event_.Wait();
-    finish_time = time::Time::Now();
+    finish_time = monotonic_clock::now();
   });
-  static const time::Time kWaitTime = time::Time::InSeconds(0.05);
+  static constexpr auto kWaitTime = chrono::milliseconds(50);
   started.Wait();
-  time::SleepFor(kWaitTime);
+  this_thread::sleep_for(kWaitTime);
   test_event_.Set();
   thread.join();
   EXPECT_GE(finish_time - start_time, kWaitTime);
 }
 
 TEST_F(EventTest, WaitTimeout) {
-  EXPECT_FALSE(test_event_.WaitTimeout(time::Time::InSeconds(0.05)));
+  EXPECT_FALSE(test_event_.WaitTimeout(chrono::milliseconds(50)));
 
-  time::Time start_time, finish_time;
+  monotonic_clock::time_point start_time, finish_time;
   // Without this, it sometimes manages to fail under tsan.
   Event started;
   ::std::thread thread([this, &start_time, &finish_time, &started]() {
-    start_time = time::Time::Now();
+    start_time = monotonic_clock::now();
     started.Set();
-    EXPECT_TRUE(test_event_.WaitTimeout(time::Time::InSeconds(0.5)));
-    finish_time = time::Time::Now();
+    EXPECT_TRUE(test_event_.WaitTimeout(chrono::milliseconds(500)));
+    finish_time = monotonic_clock::now();
   });
-  static const time::Time kWaitTime = time::Time::InSeconds(0.05);
+  constexpr auto kWaitTime = chrono::milliseconds(50);
   started.Wait();
-  time::SleepFor(kWaitTime);
+  this_thread::sleep_for(kWaitTime);
   test_event_.Set();
   thread.join();
   EXPECT_GE(finish_time - start_time, kWaitTime);
diff --git a/aos/common/logging/binary_log_writer.cc b/aos/common/logging/binary_log_writer.cc
index 10641fb..076d72d 100644
--- a/aos/common/logging/binary_log_writer.cc
+++ b/aos/common/logging/binary_log_writer.cc
@@ -1,27 +1,28 @@
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <mntent.h>
+#include <pwd.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <errno.h>
-#include <time.h>
 #include <string.h>
-#include <string>
-#include <unistd.h>
 #include <sys/types.h>
-#include <pwd.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <mntent.h>
+#include <time.h>
+#include <unistd.h>
+#include <string>
 
+#include <chrono>
 #include <map>
 #include <unordered_set>
 
-#include "aos/common/logging/implementations.h"
-#include "aos/common/logging/binary_log_file.h"
-#include "aos/linux_code/init.h"
-#include "aos/linux_code/configuration.h"
-#include "aos/linux_code/ipc_lib/queue.h"
-#include "aos/common/queue_types.h"
 #include "aos/common/die.h"
+#include "aos/common/logging/binary_log_file.h"
+#include "aos/common/logging/implementations.h"
+#include "aos/common/queue_types.h"
 #include "aos/common/time.h"
+#include "aos/linux_code/configuration.h"
+#include "aos/linux_code/init.h"
+#include "aos/linux_code/ipc_lib/queue.h"
 
 namespace aos {
 namespace logging {
@@ -213,8 +214,7 @@
       // again so the queue can buffer up some logs. This avoids lots of context
       // switches and mutex contention which happens if we're constantly reading
       // new messages as they come in.
-      static constexpr auto kSleepTime = ::aos::time::Time::InSeconds(0.1);
-      ::aos::time::SleepFor(kSleepTime);
+      ::std::this_thread::sleep_for(::std::chrono::milliseconds(100));
       continue;
     }
 
diff --git a/aos/common/logging/implementations.cc b/aos/common/logging/implementations.cc
index 2f17f7a..697dec9 100644
--- a/aos/common/logging/implementations.cc
+++ b/aos/common/logging/implementations.cc
@@ -4,6 +4,7 @@
 #include <inttypes.h>
 
 #include <algorithm>
+#include <chrono>
 
 #include "aos/common/die.h"
 #include "aos/common/once.h"
@@ -16,6 +17,8 @@
 namespace logging {
 namespace {
 
+namespace chrono = ::std::chrono;
+
 // The root LogImplementation. It only logs to stderr/stdout.
 // Some of the things specified in the LogImplementation documentation doesn't
 // apply here (mostly the parts about being able to use LOG) because this is the
@@ -84,9 +87,14 @@
   memcpy(message->name, context->name, context->name_size);
   message->name_length = context->name_size;
 
-  time::Time now = time::Time::Now();
-  message->seconds = now.sec();
-  message->nseconds = now.nsec();
+  monotonic_clock::time_point monotonic_now = monotonic_clock::now();
+  message->seconds =
+      chrono::duration_cast<chrono::seconds>(monotonic_now.time_since_epoch())
+          .count();
+  message->nseconds =
+      chrono::duration_cast<chrono::nanoseconds>(
+          monotonic_now.time_since_epoch() - chrono::seconds(message->seconds))
+          .count();
 
   message->sequence = context->sequence++;
 }
@@ -325,9 +333,9 @@
 RawQueue *queue = NULL;
 
 int dropped_messages = 0;
-::aos::time::Time dropped_start, backoff_start;
+monotonic_clock::time_point dropped_start, backoff_start;
 // Wait this long after dropping a message before even trying to write any more.
-constexpr ::aos::time::Time kDropBackoff = ::aos::time::Time::InSeconds(0.1);
+constexpr chrono::milliseconds kDropBackoff = chrono::milliseconds(100);
 
 LogMessage *GetMessageOrDie() {
   LogMessage *message = static_cast<LogMessage *>(queue->GetMessage());
@@ -340,8 +348,8 @@
 
 void Write(LogMessage *msg) {
   if (__builtin_expect(dropped_messages > 0, false)) {
-    ::aos::time::Time message_time =
-        ::aos::time::Time(msg->seconds, msg->nseconds);
+    monotonic_clock::time_point message_time(
+        chrono::seconds(msg->seconds) + chrono::nanoseconds(msg->nseconds));
     if (message_time - backoff_start < kDropBackoff) {
       ++dropped_messages;
       queue->FreeMessage(msg);
@@ -349,10 +357,16 @@
     }
 
     LogMessage *dropped_message = GetMessageOrDie();
+    chrono::seconds dropped_start_sec = chrono::duration_cast<chrono::seconds>(
+        dropped_start.time_since_epoch());
+    chrono::nanoseconds dropped_start_nsec =
+        chrono::duration_cast<chrono::nanoseconds>(
+            dropped_start.time_since_epoch() - dropped_start_sec);
     internal::FillInMessageVarargs(
         ERROR, dropped_message,
         "%d logs starting at %" PRId32 ".%" PRId32 " dropped\n",
-        dropped_messages, dropped_start.sec(), dropped_start.nsec());
+        dropped_messages, static_cast<int32_t>(dropped_start_sec.count()),
+        static_cast<int32_t>(dropped_start_nsec.count()));
     if (queue->WriteMessage(dropped_message, RawQueue::kNonBlock)) {
       dropped_messages = 0;
     } else {
@@ -367,8 +381,9 @@
   }
   if (!queue->WriteMessage(msg, RawQueue::kNonBlock)) {
     if (dropped_messages == 0) {
-      dropped_start = backoff_start =
-          ::aos::time::Time(msg->seconds, msg->nseconds);
+      monotonic_clock::time_point message_time(
+          chrono::seconds(msg->seconds) + chrono::nanoseconds(msg->nseconds));
+      dropped_start = backoff_start = message_time;
     }
     ++dropped_messages;
   }
diff --git a/aos/common/logging/implementations_test.cc b/aos/common/logging/implementations_test.cc
index bbee5b7..aade0d1 100644
--- a/aos/common/logging/implementations_test.cc
+++ b/aos/common/logging/implementations_test.cc
@@ -1,7 +1,8 @@
-#include <string>
-
 #include <inttypes.h>
 
+#include <chrono>
+#include <string>
+
 #include "gtest/gtest.h"
 
 #include "aos/common/logging/implementations.h"
@@ -16,6 +17,8 @@
 namespace logging {
 namespace testing {
 
+namespace chrono = ::std::chrono;
+
 class TestLogImplementation : public SimpleLogImplementation {
   __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 0)))
   void DoLog(log_level level, const char *format, va_list ap) override {
@@ -168,23 +171,25 @@
   //static const long kTimingCycles = 5000000;
   static const long kTimingCycles = 5000;
 
-  time::Time start = time::Time::Now();
+  monotonic_clock::time_point start = monotonic_clock::now();
   for (long i = 0; i < kTimingCycles; ++i) {
     LOG(INFO, "a\n");
   }
-  time::Time end = time::Time::Now();
-  time::Time diff = end - start;
+  monotonic_clock::time_point end = monotonic_clock::now();
+  auto diff = end - start;
   printf("short message took %" PRId64 " nsec for %ld\n",
-         diff.ToNSec(), kTimingCycles);
+         chrono::duration_cast<chrono::nanoseconds>(diff).count(),
+         kTimingCycles);
 
-  start = time::Time::Now();
+  start = monotonic_clock::now();
   for (long i = 0; i < kTimingCycles; ++i) {
     LOG(INFO, "something longer than just \"a\" to log to test timing\n");
   }
-  end = time::Time::Now();
+  end = monotonic_clock::now();
   diff = end - start;
   printf("long message took %" PRId64 " nsec for %ld\n",
-         diff.ToNSec(), kTimingCycles);
+         chrono::duration_cast<chrono::nanoseconds>(diff).count(),
+         kTimingCycles);
 }
 
 TEST(LoggingPrintFormatTest, Time) {
diff --git a/aos/common/logging/log_streamer.cc b/aos/common/logging/log_streamer.cc
index ab37e02..74e680b 100644
--- a/aos/common/logging/log_streamer.cc
+++ b/aos/common/logging/log_streamer.cc
@@ -1,40 +1,47 @@
-#include <stdio.h>
-#include <stdlib.h>
 #include <errno.h>
-#include <time.h>
-#include <string.h>
-#include <string>
-#include <unistd.h>
-#include <sys/types.h>
-#include <pwd.h>
 #include <fcntl.h>
 #include <inttypes.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <time.h>
+#include <unistd.h>
+#include <chrono>
+#include <string>
 
+#include "aos/common/logging/implementations.h"
+#include "aos/common/logging/logging.h"
+#include "aos/common/time.h"
 #include "aos/linux_code/init.h"
 #include "aos/linux_code/ipc_lib/queue.h"
-#include "aos/common/logging/logging.h"
-#include "aos/common/logging/implementations.h"
-#include "aos/common/time.h"
 
 namespace aos {
 namespace logging {
 namespace linux_code {
 namespace {
 
+namespace chrono = ::std::chrono;
+
 int LogStreamerMain() {
   InitNRT();
 
   RawQueue *queue = GetLoggingQueue();
 
-  const time::Time now = time::Time::Now();
+  const monotonic_clock::time_point now = monotonic_clock::now();
+  chrono::seconds sec =
+      chrono::duration_cast<chrono::seconds>(now.time_since_epoch());
+  chrono::nanoseconds nsec =
+      chrono::duration_cast<chrono::nanoseconds>(now.time_since_epoch() - sec);
   printf("starting at %" PRId32 "s%" PRId32 "ns-----------------------------\n",
-         now.sec(), now.nsec());
+         static_cast<int32_t>(sec.count()), static_cast<int32_t>(nsec.count()));
 
   while (true) {
     const LogMessage *const msg = static_cast<const LogMessage *>(
         queue->ReadMessage(RawQueue::kNonBlock));
     if (msg == NULL) {
-      ::aos::time::SleepFor(::aos::time::Time::InSeconds(0.1));
+      ::std::this_thread::sleep_for(::std::chrono::milliseconds(100));
     } else {
       internal::PrintMessage(stdout, *msg);
 
diff --git a/aos/common/logging/replay.cc b/aos/common/logging/replay.cc
index 7180c96..6b55e51 100644
--- a/aos/common/logging/replay.cc
+++ b/aos/common/logging/replay.cc
@@ -1,9 +1,13 @@
 #include "aos/common/logging/replay.h"
 
+#include <chrono>
+
 namespace aos {
 namespace logging {
 namespace linux_code {
 
+namespace chrono = ::std::chrono;
+
 bool LogReplayer::ProcessMessage() {
   const LogFileMessageHeader *message = reader_->ReadNextMessage(false);
   if (message == nullptr) return true;
@@ -32,8 +36,9 @@
   if (handler == handlers_.end()) return false;
 
   handler->second->HandleStruct(
-      ::aos::time::Time(message->time_sec, message->time_nsec), type_id,
-      position,
+      monotonic_clock::time_point(chrono::seconds(message->time_sec) +
+                                  chrono::nanoseconds(message->time_nsec)),
+      type_id, position,
       message->message_size -
           (sizeof(type_id) + sizeof(message_length) + message_length));
   return false;
diff --git a/aos/common/logging/replay.h b/aos/common/logging/replay.h
index 38f7120..1a8418f 100644
--- a/aos/common/logging/replay.h
+++ b/aos/common/logging/replay.h
@@ -80,8 +80,9 @@
    public:
     virtual ~StructHandlerInterface() {}
 
-    virtual void HandleStruct(::aos::time::Time log_time, uint32_t type_id,
-                              const void *data, size_t data_size) = 0;
+    virtual void HandleStruct(::aos::monotonic_clock::time_point log_time,
+                              uint32_t type_id, const void *data,
+                              size_t data_size) = 0;
   };
 
   // Converts struct log messages to a message type and passes it to an
@@ -92,8 +93,9 @@
     TypedStructHandler(::std::function<void(const T &message)> handler)
         : handler_(handler) {}
 
-    void HandleStruct(::aos::time::Time log_time, uint32_t type_id,
-                      const void *data, size_t data_size) override {
+    void HandleStruct(::aos::monotonic_clock::time_point log_time,
+                      uint32_t type_id, const void *data,
+                      size_t data_size) override {
       CHECK_EQ(type_id, T::GetType()->id);
       T message;
       CHECK_EQ(data_size, T::Size());
diff --git a/aos/common/mutex_test.cc b/aos/common/mutex_test.cc
index 8cc4e73..3717109 100644
--- a/aos/common/mutex_test.cc
+++ b/aos/common/mutex_test.cc
@@ -1,25 +1,29 @@
 #include "aos/common/mutex.h"
 
-#include <sched.h>
 #include <math.h>
 #include <pthread.h>
+#include <sched.h>
 
+#include <chrono>
 #include <thread>
 
 #include "gtest/gtest.h"
 
-#include "aos/linux_code/ipc_lib/aos_sync.h"
 #include "aos/common/die.h"
+#include "aos/common/time.h"
 #include "aos/common/util/death_test_log_implementation.h"
 #include "aos/common/util/thread.h"
-#include "aos/common/time.h"
+#include "aos/linux_code/ipc_lib/aos_sync.h"
+#include "aos/linux_code/ipc_lib/core_lib.h"
 #include "aos/testing/test_logging.h"
 #include "aos/testing/test_shm.h"
-#include "aos/linux_code/ipc_lib/core_lib.h"
 
 namespace aos {
 namespace testing {
 
+namespace chrono = ::std::chrono;
+namespace this_thread = ::std::this_thread;
+
 class MutexTest : public ::testing::Test {
  public:
   Mutex test_mutex_;
@@ -169,8 +173,9 @@
 
 class AdderThread : public ::aos::util::Thread {
  public:
-  AdderThread(int *counter, Mutex *mutex, ::aos::time::Time sleep_before_time,
-              ::aos::time::Time sleep_after_time)
+  AdderThread(int *counter, Mutex *mutex,
+              monotonic_clock::duration sleep_before_time,
+              monotonic_clock::duration sleep_after_time)
       : counter_(counter),
         mutex_(mutex),
         sleep_before_time_(sleep_before_time),
@@ -178,15 +183,15 @@
 
  private:
   virtual void Run() override {
-    ::aos::time::SleepFor(sleep_before_time_);
+    this_thread::sleep_for(sleep_before_time_);
     MutexLocker locker(mutex_);
     ++(*counter_);
-    ::aos::time::SleepFor(sleep_after_time_);
+    this_thread::sleep_for(sleep_after_time_);
   }
 
   int *const counter_;
   Mutex *const mutex_;
-  const ::aos::time::Time sleep_before_time_, sleep_after_time_;
+  const monotonic_clock::duration sleep_before_time_, sleep_after_time_;
 };
 
 }  // namespace
@@ -196,10 +201,11 @@
 TEST_F(MutexTest, ThreadSanitizerContended) {
   int counter = 0;
   AdderThread threads[2]{
-      {&counter, &test_mutex_, ::aos::time::Time::InSeconds(0.2),
-       ::aos::time::Time::InSeconds(0)},
-      {&counter, &test_mutex_, ::aos::time::Time::InSeconds(0),
-       ::aos::time::Time::InSeconds(0)}, };
+      {&counter, &test_mutex_, chrono::milliseconds(200),
+       chrono::milliseconds(0)},
+      {&counter, &test_mutex_, chrono::milliseconds(0),
+       chrono::milliseconds(0)},
+  };
   for (auto &c : threads) {
     c.Start();
   }
@@ -235,10 +241,10 @@
 TEST_F(MutexTest, ThreadSanitizerUncontended) {
   int counter = 0;
   AdderThread threads[2]{
-      {&counter, &test_mutex_, ::aos::time::Time::InSeconds(0),
-       ::aos::time::Time::InSeconds(0)},
-      {&counter, &test_mutex_, ::aos::time::Time::InSeconds(0.2),
-       ::aos::time::Time::InSeconds(0)}, };
+      {&counter, &test_mutex_, chrono::milliseconds(0),
+       chrono::milliseconds(0)},
+      {&counter, &test_mutex_, chrono::milliseconds(200),
+       chrono::milliseconds(0)}, };
   for (auto &c : threads) {
     c.Start();
   }
diff --git a/aos/common/network/socket.cc b/aos/common/network/socket.cc
index b674ff1..80eca70 100644
--- a/aos/common/network/socket.cc
+++ b/aos/common/network/socket.cc
@@ -1,15 +1,18 @@
 #include "aos/common/network/socket.h"
 
-#include <string.h>
 #include <errno.h>
+#include <string.h>
 #include <sys/socket.h>
+#include <chrono>
 
-#include "aos/common/logging/logging.h"
 #include "aos/common/byteorder.h"
+#include "aos/common/logging/logging.h"
 
 namespace aos {
 namespace network {
 
+namespace chrono = ::std::chrono;
+
 int Socket::Connect(NetworkPort port, const char *address, int type) {
   last_ret_ = 0;
   if ((socket_ = socket(AF_INET, type, 0)) < 0) {
@@ -53,8 +56,13 @@
   return ret;
 }
 
-int Socket::Receive(void *buf, int length, time::Time timeout) {
-  timeval timeout_timeval = timeout.ToTimeval();
+int Socket::Receive(void *buf, int length, chrono::microseconds timeout) {
+  timeval timeout_timeval;
+  timeout_timeval.tv_sec = chrono::duration_cast<chrono::seconds>(timeout).count();
+  timeout_timeval.tv_usec =
+      chrono::duration_cast<chrono::microseconds>(
+          timeout - chrono::seconds(timeout_timeval.tv_sec))
+          .count();
   fd_set fds;
   FD_ZERO(&fds);
   FD_SET(socket_, &fds);
diff --git a/aos/common/network/socket.h b/aos/common/network/socket.h
index 9e8eaf5..9bda8aa 100644
--- a/aos/common/network/socket.h
+++ b/aos/common/network/socket.h
@@ -1,15 +1,15 @@
 #ifndef AOS_COMMON_NETWORK_SOCKET_H_
 #define AOS_COMMON_NETWORK_SOCKET_H_
 
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
 #include <sys/socket.h>
 #include <sys/types.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <stdlib.h>
 #include <unistd.h>
-#include <stdio.h>
+#include <chrono>
 
-#include "aos/common/time.h"
 #include "aos/common/network_port.h"
 
 namespace aos {
@@ -28,7 +28,7 @@
   // No timeout.
   int Receive(void *buf, int length);
   // timeout is relative
-  int Receive(void *buf, int length, time::Time timeout);
+  int Receive(void *buf, int length, ::std::chrono::microseconds timeout);
 
  protected:
   int Connect(NetworkPort port, const char *address, int type = SOCK_DGRAM);
diff --git a/aos/common/queue.cc b/aos/common/queue.cc
index 893e62b..ba85a72 100644
--- a/aos/common/queue.cc
+++ b/aos/common/queue.cc
@@ -1,37 +1,47 @@
 #include "aos/common/queue.h"
 
-#include "aos/common/byteorder.h"
 #include <inttypes.h>
+#include <chrono>
+
+#include "aos/common/byteorder.h"
 
 namespace aos {
 
-void Message::Zero() {
-  sent_time.set_sec(0);
-  sent_time.set_nsec(0);
-}
+namespace chrono = ::std::chrono;
+
+void Message::Zero() { sent_time = monotonic_clock::min_time; }
 
 size_t Message::Deserialize(const char *buffer) {
   int32_t sec;
   int32_t nsec;
   to_host(&buffer[0], &sec);
   to_host(&buffer[4], &nsec);
-  sent_time.set_sec(sec);
-  sent_time.set_nsec(nsec);
+  sent_time = monotonic_clock::time_point(chrono::seconds(sec) +
+                                          chrono::nanoseconds(nsec));
   return Size();
 }
 // Serializes the common fields into the buffer.
 size_t Message::Serialize(char *buffer) const {
   // TODO(aschuh): to_network shouldn't need a pointer.
-  int32_t sec = sent_time.sec();
-  int32_t nsec = sent_time.nsec();
+  int32_t sec =
+      chrono::duration_cast<chrono::seconds>(sent_time.time_since_epoch())
+          .count();
+  int32_t nsec = chrono::duration_cast<chrono::nanoseconds>(
+                     sent_time.time_since_epoch() - chrono::seconds(sec))
+                     .count();
   to_network(&sec, &buffer[0]);
   to_network(&nsec, &buffer[4]);
   return Size();
 }
 
 size_t Message::Print(char *buffer, int length) const {
-  return snprintf(buffer, length, "%" PRId32 ".%09" PRId32 "s",
-                  sent_time.sec(), sent_time.nsec());
+  int32_t sec =
+      chrono::duration_cast<chrono::seconds>(sent_time.time_since_epoch())
+          .count();
+  int32_t nsec = chrono::duration_cast<chrono::nanoseconds>(
+                     sent_time.time_since_epoch() - chrono::seconds(sec))
+                     .count();
+  return snprintf(buffer, length, "%" PRId32 ".%09" PRId32 "s", sec, nsec);
 }
 
 }  // namespace aos
diff --git a/aos/common/queue.h b/aos/common/queue.h
index 5f5d8b0..7f43a3e 100644
--- a/aos/common/queue.h
+++ b/aos/common/queue.h
@@ -16,16 +16,15 @@
 // thing for the whole thing.
 class Message {
  public:
-  typedef ::aos::time::Time Time;
   // The time that the message was sent at.
-  Time sent_time;
+  monotonic_clock::time_point sent_time;
 
-  Message() : sent_time(0, 0) {}
+  Message() : sent_time(monotonic_clock::min_time) {}
 
   // Zeros out the time.
   void Zero();
   // Returns the size of the common fields.
-  static size_t Size() { return sizeof(Time); }
+  static size_t Size() { return sizeof(sent_time); }
 
   // Deserializes the common fields from the buffer.
   size_t Deserialize(const char *buffer);
@@ -33,7 +32,7 @@
   size_t Serialize(char *buffer) const;
 
   // Populates sent_time with the current time.
-  void SetTimeToNow() { sent_time = Time::Now(); }
+  void SetTimeToNow() { sent_time = monotonic_clock::now(); }
 
   // Writes the contents of the message to the provided buffer.
   size_t Print(char *buffer, int length) const;
@@ -198,18 +197,11 @@
   void FetchAnother();
 
   // Returns the age of the message.
-  const time::Time Age() const {
-    return time::Time::Now() - queue_msg_->sent_time;
+  const monotonic_clock::duration Age() const {
+    return monotonic_clock::now() - queue_msg_->sent_time;
   }
 
-  // Returns true if the latest value in the queue is newer than age mseconds.
-  // DEPRECATED(brians): Use IsNewerThan(const time::Time&) instead.
-  bool IsNewerThanMS(int age) const {
-    // TODO(aschuh): Log very verbosely if something is _ever_ stale.
-    return IsNewerThan(time::Time::InMS(age));
-  }
-
-  bool IsNewerThan(const time::Time &age) const {
+  bool IsNewerThan(const monotonic_clock::duration age) const {
     return get() != nullptr && Age() < age;
   }
 
diff --git a/aos/common/queue_test.cc b/aos/common/queue_test.cc
index dc8c62c..eb109ba 100644
--- a/aos/common/queue_test.cc
+++ b/aos/common/queue_test.cc
@@ -1,20 +1,21 @@
 #include <unistd.h>
 
+#include <chrono>
 #include <memory>
 
 #include "gtest/gtest.h"
 
+#include "aos/common/die.h"
 #include "aos/common/test_queue.q.h"
 #include "aos/common/util/thread.h"
-#include "aos/common/die.h"
 #include "aos/testing/test_shm.h"
 
-using ::aos::time::Time;
-
 namespace aos {
 namespace common {
 namespace testing {
 
+namespace chrono = ::std::chrono;
+
 class QueueTest : public ::testing::Test {
  protected:
   void SetUp() override {
@@ -54,7 +55,7 @@
   usleep(50000);
   my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x971).Send();
   t.Join();
-  EXPECT_LE(t.threaded_test_queue.Age(), time::Time::InMS(57));
+  EXPECT_LE(t.threaded_test_queue.Age(), chrono::milliseconds(57));
 }
 
 // Tests that we can send a message with the message pointer and get it back.
@@ -76,7 +77,7 @@
   ASSERT_TRUE(my_test_queue.FetchLatest());
   EXPECT_EQ(true, my_test_queue->test_bool);
   EXPECT_EQ(0x971, my_test_queue->test_int);
-  EXPECT_EQ(true, my_test_queue.IsNewerThanMS(10000));
+  EXPECT_EQ(true, my_test_queue.IsNewerThan(chrono::milliseconds(10000)));
 }
 
 // Tests that multiple queue instances don't break each other.
@@ -202,10 +203,9 @@
   my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x971).Send();
 
   ASSERT_TRUE(my_test_queue.FetchLatest());
-  EXPECT_TRUE(my_test_queue.IsNewerThanMS(100));
-  const Time age = my_test_queue.Age();
-  EXPECT_EQ(0, age.sec());
-  EXPECT_GE(100000000, age.nsec());
+  EXPECT_TRUE(my_test_queue.IsNewerThan(chrono::milliseconds(100)));
+  const auto age = my_test_queue.Age();
+  EXPECT_GE(chrono::nanoseconds(100000000), age);
 }
 
 
@@ -257,8 +257,7 @@
 
   EXPECT_FALSE(msg.test_bool);
   EXPECT_EQ(0, msg.test_int);
-  EXPECT_EQ(0, msg.sent_time.sec());
-  EXPECT_EQ(0, msg.sent_time.nsec());
+  EXPECT_EQ(monotonic_clock::min_time, msg.sent_time);
 }
 
 TEST_F(MessageTest, Size) {
@@ -286,7 +285,8 @@
   char printdata[1024];
   msg.test_bool = true;
   msg.test_int = 2056;
-  msg.sent_time = Time(971, 254);
+  msg.sent_time = monotonic_clock::time_point(chrono::seconds(971) +
+                                              chrono::nanoseconds(254));
 
   std::string golden("971.000000254s, T, 2056");
   EXPECT_EQ(golden.size(), msg.Print(printdata, sizeof(printdata)));
@@ -304,7 +304,7 @@
 
 TEST_F(MessageTest, SetNow) {
   msg.SetTimeToNow();
-  EXPECT_LE(msg.sent_time - Time::Now(), Time::InMS(20));
+  EXPECT_LE(msg.sent_time - monotonic_clock::now(), chrono::milliseconds(20));
 }
 
 // Tests that EqualsNoTime works.
diff --git a/aos/common/time.cc b/aos/common/time.cc
index 7cfc4bc..e8bd25b 100644
--- a/aos/common/time.cc
+++ b/aos/common/time.cc
@@ -1,9 +1,10 @@
 #include "aos/common/time.h"
 
-#include <atomic>
-
-#include <string.h>
 #include <inttypes.h>
+#include <string.h>
+
+#include <atomic>
+#include <chrono>
 
 // We only use global_core from here, which is weak, so we don't really have a
 // dependency on it.
@@ -12,6 +13,8 @@
 #include "aos/common/logging/logging.h"
 #include "aos/common/mutex.h"
 
+namespace chrono = ::std::chrono;
+
 namespace std {
 namespace this_thread {
 template <>
@@ -57,34 +60,8 @@
 // Current time when time is mocked.
 monotonic_clock::time_point current_mock_time = monotonic_clock::epoch();
 
-// TODO(aschuh): This doesn't include SleepFor and SleepUntil.
-// TODO(aschuh): Create a clock source object and change the default?
-//  That would let me create a MockTime clock source.
-
-Time NowImpl(clockid_t clock) {
-  timespec temp;
-  if (clock_gettime(clock, &temp) != 0) {
-    PLOG(FATAL, "clock_gettime(%jd, %p) failed",
-         static_cast<uintmax_t>(clock), &temp);
-  }
-
-  const timespec offset = (&global_core == nullptr || global_core == nullptr ||
-                           global_core->mem_struct == nullptr)
-                              ? timespec{0, 0}
-                              : global_core->mem_struct->time_offset;
-  return Time(temp) + Time(offset);
-}
-
 }  // namespace
 
-const int32_t Time::kNSecInSec;
-const int32_t Time::kNSecInMSec;
-const int32_t Time::kNSecInUSec;
-const int32_t Time::kMSecInSec;
-const int32_t Time::kUSecInSec;
-
-const Time Time::kZero{0, 0};
-
 void EnableMockTime(monotonic_clock::time_point now) {
   MutexLocker time_mutex_locker(&time_mutex);
   mock_time_enabled = true;
@@ -112,162 +89,13 @@
   SetMockTime(monotonic_clock::now() + amount);
 }
 
-Time Time::Now(clockid_t clock) {
-  {
-    if (mock_time_enabled.load(::std::memory_order_relaxed)) {
-      MutexLocker time_mutex_locker(&time_mutex);
-      return Time::InNS(
-          ::std::chrono::duration_cast<::std::chrono::nanoseconds>(
-              current_mock_time.time_since_epoch()).count());
-    }
-  }
-  return NowImpl(clock);
-}
-
-void Time::CheckImpl(int32_t nsec) {
-  static_assert(aos::shm_ok<Time>::value,
-                "it should be able to go through shared memory");
-  if (nsec >= kNSecInSec || nsec < 0) {
-    LOG(FATAL, "0 <= nsec(%" PRId32 ") < %" PRId32 " isn't true.\n",
-        nsec, kNSecInSec);
-  }
-}
-
-Time &Time::operator+=(const Time &rhs) {
-  sec_ += rhs.sec_;
-  nsec_ += rhs.nsec_;
-  if (nsec_ >= kNSecInSec) {
-    nsec_ -= kNSecInSec;
-    sec_ += 1;
-  }
-  return *this;
-}
-const Time Time::operator+(const Time &rhs) const {
-  return Time(*this) += rhs;
-}
-Time &Time::operator-=(const Time &rhs) {
-  sec_ -= rhs.sec_;
-  nsec_ -= rhs.nsec_;
-  if (nsec_ < 0) {
-    nsec_ += kNSecInSec;
-    sec_ -= 1;
-  }
-  return *this;
-}
-const Time Time::operator-(const Time &rhs) const {
-  return Time(*this) -= rhs;
-}
-Time &Time::operator*=(int32_t rhs) {
-  const int64_t temp = static_cast<int64_t>(nsec_) *
-      static_cast<int64_t>(rhs);
-  sec_ *= rhs;  // better not overflow, or the result is just too big
-  nsec_ = temp % kNSecInSec;
-  sec_ += (temp - nsec_) / kNSecInSec;
-  if (nsec_ < 0) {
-    nsec_ += kNSecInSec;
-    sec_ -= 1;
-  }
-  return *this;
-}
-const Time Time::operator*(int32_t rhs) const {
-  return Time(*this) *= rhs;
-}
-Time &Time::operator/=(int32_t rhs) {
-  nsec_ = (sec_ % rhs) * (kNSecInSec / rhs) + nsec_ / rhs;
-  sec_ /= rhs;
-  if (nsec_ < 0) {
-    nsec_ += kNSecInSec;
-    sec_ -= 1;
-  }
-  return *this;
-}
-const Time Time::operator/(int32_t rhs) const {
-  return Time(*this) /= rhs;
-}
-double Time::operator/(const Time &rhs) const {
-  return ToSeconds() / rhs.ToSeconds();
-}
-Time &Time::operator%=(int32_t rhs) {
-  nsec_ = ToNSec() % rhs;
-  const int wraps = nsec_ / ((rhs / kNSecInSec + 1) * kNSecInSec);
-  sec_ = wraps + rhs / kNSecInSec;
-  nsec_ -= kNSecInSec * wraps;
-  if (nsec_ < 0) {
-    nsec_ += kNSecInSec;
-    sec_ -= 1;
-  }
-  return *this;
-}
-const Time Time::operator%(int32_t rhs) const {
-  return Time(*this) %= rhs;
-}
-
-const Time Time::operator-() const {
-  return Time(-sec_ - 1, kNSecInSec - nsec_);
-}
-
-bool Time::operator==(const Time &rhs) const {
-  return sec_ == rhs.sec_ && nsec_ == rhs.nsec_;
-}
-bool Time::operator!=(const Time &rhs) const {
-  return !(*this == rhs);
-}
-bool Time::operator<(const Time &rhs) const {
-  return sec_ < rhs.sec_ || (sec_ == rhs.sec_ && nsec_ < rhs.nsec_);
-}
-bool Time::operator>(const Time &rhs) const {
-  return sec_ > rhs.sec_ || (sec_ == rhs.sec_ && nsec_ > rhs.nsec_);
-}
-bool Time::operator<=(const Time &rhs) const {
-  return sec_ < rhs.sec_ || (sec_ == rhs.sec_ && nsec_ <= rhs.nsec_);
-}
-bool Time::operator>=(const Time &rhs) const {
-  return sec_ > rhs.sec_ || (sec_ == rhs.sec_ && nsec_ >= rhs.nsec_);
-}
-
-bool Time::IsWithin(const Time &other, int64_t amount) const {
-  const int64_t temp = ToNSec() - other.ToNSec();
-  return temp <= amount && temp >= -amount;
-}
-
-std::ostream &operator<<(std::ostream &os, const Time& time) {
-  return os << "Time{" << time.sec_ << "s, " << time.nsec_ << "ns}";
-}
-
-void SleepFor(const Time &time, clockid_t clock) {
-  timespec converted(time.ToTimespec()), remaining;
-  int failure = EINTR;
-  do {
-    // This checks whether the last time through the loop actually failed or got
-    // interrupted.
-    if (failure != EINTR) {
-      PELOG(FATAL, failure, "clock_nanosleep(%jd, 0, %p, %p) failed",
-            static_cast<intmax_t>(clock), &converted, &remaining);
-    }
-    failure = clock_nanosleep(clock, 0, &converted, &remaining);
-    memcpy(&converted, &remaining, sizeof(converted));
-  } while (failure != 0);
-}
-
-void SleepUntil(const Time &time, clockid_t clock) {
-  timespec converted(time.ToTimespec());
-  int failure;
-  while ((failure = clock_nanosleep(clock, TIMER_ABSTIME,
-                                    &converted, NULL)) != 0) {
-    if (failure != EINTR) {
-      PELOG(FATAL, failure, "clock_nanosleep(%jd, TIMER_ABSTIME, %p, NULL)"
-            " failed", static_cast<intmax_t>(clock), &converted);
-    }
-  }
-}
-
-void OffsetToNow(const Time &now) {
+void OffsetToNow(monotonic_clock::time_point now) {
   CHECK_NOTNULL(&global_core);
   CHECK_NOTNULL(global_core);
   CHECK_NOTNULL(global_core->mem_struct);
-  global_core->mem_struct->time_offset.tv_nsec = 0;
-  global_core->mem_struct->time_offset.tv_sec = 0;
-  global_core->mem_struct->time_offset = (now - Time::Now()).ToTimespec();
+  const auto offset = now - monotonic_clock::now();
+  global_core->mem_struct->time_offset =
+      chrono::duration_cast<chrono::nanoseconds>(offset).count();
 }
 
 }  // namespace time
@@ -287,8 +115,14 @@
     PLOG(FATAL, "clock_gettime(%jd, %p) failed",
          static_cast<uintmax_t>(CLOCK_MONOTONIC), &current_time);
   }
+  const chrono::nanoseconds offset =
+      (&global_core == nullptr || global_core == nullptr ||
+       global_core->mem_struct == nullptr)
+          ? chrono::nanoseconds(0)
+          : chrono::nanoseconds(global_core->mem_struct->time_offset);
+
   return time_point(::std::chrono::seconds(current_time.tv_sec) +
-                    ::std::chrono::nanoseconds(current_time.tv_nsec));
+                    ::std::chrono::nanoseconds(current_time.tv_nsec)) + offset;
 }
 
 
diff --git a/aos/common/time.h b/aos/common/time.h
index ab64916..e541932 100644
--- a/aos/common/time.h
+++ b/aos/common/time.h
@@ -52,244 +52,23 @@
 // Disables mocking time.
 void DisableMockTime();
 
-// A nice structure for representing times.
-// 0 <= nsec_ < kNSecInSec should always be true. All functions here will make
-// sure that that is true if it was on all inputs (including *this).
-//
-// Negative times are supported so that all of the normal arithmetic identities
-// work. nsec_ is still always positive.
-//
-// The arithmetic and comparison operators are overloaded because they make
-// complete sense and are very useful. The default copy and assignment stuff is
-// left because it works fine. Multiplication of Times by Times is
-// not implemented because I can't think of any uses for them and there are
-// multiple ways to do it. Division of Times by Times is implemented as the
-// ratio of them. Multiplication, division, and modulus of Times by integers are
-// implemented as interpreting the argument as nanoseconds. Modulus takes the
-// sign from the first operand.
-struct Time {
-#ifdef SWIG
-// All of the uses of constexpr here can safely be simply removed.
-// NOTE: This means that relying on the fact that constexpr implicitly makes
-// member functions const is not valid, so they all have to be explicitly marked
-// const.
-#define constexpr
-#endif  // SWIG
- public:
-  static const int32_t kNSecInSec = 1000000000;
-  static const int32_t kNSecInMSec = 1000000;
-  static const int32_t kNSecInUSec = 1000;
-  static const int32_t kMSecInSec = 1000;
-  static const int32_t kUSecInSec = 1000000;
-
-  static const Time kZero;
-
-  explicit constexpr Time(int32_t sec = 0, int32_t nsec = 0)
-      : sec_(sec), nsec_(CheckConstexpr(nsec)) {
-  }
-  #ifndef SWIG
-  explicit constexpr Time(const struct timespec &value)
-      : sec_(value.tv_sec), nsec_(CheckConstexpr(value.tv_nsec)) {
-  }
-  struct timespec ToTimespec() const {
-    struct timespec ans;
-    ans.tv_sec = sec_;
-    ans.tv_nsec = nsec_;
-    return ans;
-  }
-  explicit constexpr Time(const struct timeval &value)
-      : sec_(value.tv_sec), nsec_(CheckConstexpr(value.tv_usec * kNSecInUSec)) {
-  }
-  struct timeval ToTimeval() const {
-    struct timeval ans;
-    ans.tv_sec = sec_;
-    ans.tv_usec = nsec_ / kNSecInUSec;
-    return ans;
-  }
-  #endif  // SWIG
-
-  // CLOCK_MONOTONIC on linux and CLOCK_REALTIME on the cRIO because the
-  // cRIO doesn't have any others.
-  // CLOCK_REALTIME is the default realtime clock and CLOCK_MONOTONIC doesn't
-  // change when somebody changes the wall clock (like the ntp deamon or
-  // whatever). See clock_gettime(2) for details.
-  //
-  // This is the clock that code that just wants to sleep for a certain amount
-  // of time or measure how long something takes should use.
-  #ifndef __VXWORKS__
-  static const clockid_t kDefaultClock = CLOCK_MONOTONIC;
-  #else
-  static const clockid_t kDefaultClock = CLOCK_REALTIME;
-  #endif
-  // Creates a Time representing the current value of the specified clock or
-  // dies.
-  static Time Now(clockid_t clock = kDefaultClock);
-
-  // Constructs a Time representing seconds.
-  static constexpr Time InSeconds(double seconds) {
-    return (seconds < 0.0) ?
-        Time(static_cast<int32_t>(seconds) - 1,
-             (seconds - static_cast<int32_t>(seconds) + 1.0) * kNSecInSec) :
-        Time(static_cast<int32_t>(seconds),
-             (seconds - static_cast<int32_t>(seconds)) * kNSecInSec);
-  }
-
-  // Constructs a time representing microseconds.
-  static constexpr Time InNS(int64_t nseconds) {
-    return (nseconds < 0)
-               ? Time((nseconds - 1) / static_cast<int64_t>(kNSecInSec) - 1,
-                      (((nseconds - 1) % kNSecInSec) + 1) + kNSecInSec)
-               : Time(nseconds / static_cast<int64_t>(kNSecInSec),
-                      nseconds % kNSecInSec);
-  }
-
-  // Constructs a time representing microseconds.
-  static constexpr Time InUS(int useconds) {
-    return (useconds < 0)
-               ? Time((useconds + 1) / kUSecInSec - 1,
-                      (((useconds + 1) % kUSecInSec) - 1) * kNSecInUSec +
-                          kNSecInSec)
-               : Time(useconds / kUSecInSec,
-                      (useconds % kUSecInSec) * kNSecInUSec);
-  }
-
-  // Constructs a time representing mseconds.
-  static constexpr Time InMS(int mseconds) {
-    return (mseconds < 0)
-               ? Time((mseconds + 1) / kMSecInSec - 1,
-                      (((mseconds + 1) % kMSecInSec) - 1) * kNSecInMSec +
-                          kNSecInSec)
-               : Time(mseconds / kMSecInSec,
-                      (mseconds % kMSecInSec) * kNSecInMSec);
-  }
-
-  // Construct a time representing the period of hertz.
-  static constexpr ::std::chrono::nanoseconds FromRate(int hertz) {
-    return ::std::chrono::duration_cast<::std::chrono::nanoseconds>(
-               ::std::chrono::seconds(1)) /
-           hertz;
-  }
-
-  // Checks whether or not this time is within amount nanoseconds of other.
-  bool IsWithin(const Time &other, int64_t amount) const;
-
-  // Returns the time represented all in nanoseconds.
-  int64_t constexpr ToNSec() const {
-    return static_cast<int64_t>(sec_) * static_cast<int64_t>(kNSecInSec) +
-        static_cast<int64_t>(nsec_);
-  }
-#ifdef __VXWORKS__
-  // Returns the time represented all in system clock ticks. The system clock
-  // rate is retrieved using sysClkRateGet().
-  int ToTicks() const {
-    return ToNSec() / static_cast<int64_t>(kNSecInSec / sysClkRateGet());
-  }
-  // Constructs a Time representing ticks.
-  static Time InTicks(int ticks) {
-    return Time::InSeconds(static_cast<double>(ticks) / sysClkRateGet());
-  }
-#endif
-
-  // Returns the time represented in milliseconds.
-  int64_t constexpr ToMSec() const {
-    return static_cast<int64_t>(sec_) * static_cast<int64_t>(kMSecInSec) +
-        (static_cast<int64_t>(nsec_) / static_cast<int64_t>(kNSecInMSec));
-  }
-
-  // Returns the time represent in microseconds.
-  int64_t constexpr ToUSec() const {
-    return static_cast<int64_t>(sec_) * static_cast<int64_t>(kUSecInSec) +
-        (static_cast<int64_t>(nsec_) / static_cast<int64_t>(kNSecInUSec));
-  }
-
-  // Returns the time represented in fractional seconds.
-  double constexpr ToSeconds() const {
-    return static_cast<double>(sec_) + static_cast<double>(nsec_) / kNSecInSec;
-  }
-
-  #ifndef SWIG
-  Time &operator+=(const Time &rhs);
-  Time &operator-=(const Time &rhs);
-  Time &operator*=(int32_t rhs);
-  Time &operator/=(int32_t rhs);
-  Time &operator%=(int32_t rhs);
-  Time &operator%=(double rhs) = delete;
-  Time &operator*=(double rhs) = delete;
-  Time &operator/=(double rhs) = delete;
-  const Time operator*(double rhs) const = delete;
-  const Time operator/(double rhs) const = delete;
-  const Time operator%(double rhs) const = delete;
-  #endif
-  const Time operator+(const Time &rhs) const;
-  const Time operator-(const Time &rhs) const;
-  const Time operator*(int32_t rhs) const;
-  const Time operator/(int32_t rhs) const;
-  double operator/(const Time &rhs) const;
-  const Time operator%(int32_t rhs) const;
-
-  const Time operator-() const;
-
-  bool operator==(const Time &rhs) const;
-  bool operator!=(const Time &rhs) const;
-  bool operator<(const Time &rhs) const;
-  bool operator>(const Time &rhs) const;
-  bool operator<=(const Time &rhs) const;
-  bool operator>=(const Time &rhs) const;
-
-  #ifndef SWIG
-  // For gtest etc.
-  friend std::ostream &operator<<(std::ostream &os, const Time &time);
-  #endif  // SWIG
-
-  int32_t constexpr sec() const { return sec_; }
-  void set_sec(int32_t sec) { sec_ = sec; }
-  int32_t constexpr nsec() const { return nsec_; }
-  void set_nsec(int32_t nsec) {
-    nsec_ = nsec;
-    Check();
-  }
-
-  // Absolute value.
-  Time abs() const {
-    if (*this > Time(0, 0)) return *this;
-    if (nsec_ == 0) return Time(-sec_, 0);
-    return Time(-sec_ - 1, kNSecInSec - nsec_);
-  }
-
- private:
-  int32_t sec_, nsec_;
-
-  // LOG(FATAL)s if nsec is >= kNSecInSec or negative.
-  static void CheckImpl(int32_t nsec);
-  void Check() { CheckImpl(nsec_); }
-  // A constexpr version of CheckImpl that returns the given value when it
-  // succeeds or evaluates to non-constexpr and returns 0 when it fails.
-  // This will result in the usual LOG(FATAL) if this is used where it isn't
-  // required to be constexpr or a compile error if it is.
-  static constexpr int32_t CheckConstexpr(int32_t nsec) {
-    return (nsec >= kNSecInSec || nsec < 0) ? CheckImpl(nsec), 0 : nsec;
-  }
-
-#ifdef SWIG
-#undef constexpr
-#endif  // SWIG
-};
-
-// Sleeps for the amount of time represented by time counted by clock.
-void SleepFor(const Time &time, clockid_t clock = Time::kDefaultClock);
-// Sleeps until clock is at the time represented by time.
-void SleepUntil(const Time &time, clockid_t clock = Time::kDefaultClock);
-
-// Sets the global offset for all times so ::aos::time::Time::Now() will return
+// Sets the global offset for all times so monotonic_clock::now() will return
 // now.
 // There is no synchronization here, so this is only safe when only a single
 // task is running.
 // This is only allowed when the shared memory core infrastructure has been
 // initialized in this process.
-void OffsetToNow(const Time &now);
+void OffsetToNow(const monotonic_clock::time_point now);
 
-// RAII class that freezes Time::Now() (to avoid making large numbers of
-// syscalls to find the real time).
+// Construct a time representing the period of hertz.
+constexpr ::std::chrono::nanoseconds FromRate(int hertz) {
+  return ::std::chrono::duration_cast<::std::chrono::nanoseconds>(
+             ::std::chrono::seconds(1)) /
+         hertz;
+}
+
+// RAII class that freezes monotonic_clock::now() (to avoid making large numbers
+// of syscalls to find the real time).
 class TimeFreezer {
  public:
   TimeFreezer() { EnableMockTime(monotonic_clock::now()); }
diff --git a/aos/common/time_test.cc b/aos/common/time_test.cc
index e1811db..94102a2 100644
--- a/aos/common/time_test.cc
+++ b/aos/common/time_test.cc
@@ -11,251 +11,9 @@
 namespace time {
 namespace testing {
 
-TEST(TimeTest, timespecConversions) {
-  timespec start{1234, 5678};  // NOLINT
-  Time time(start);
-  EXPECT_EQ(start.tv_sec, static_cast<time_t>(time.sec()));
-  EXPECT_EQ(start.tv_nsec, time.nsec());
-  timespec end = time.ToTimespec();
-  EXPECT_EQ(start.tv_sec, end.tv_sec);
-  EXPECT_EQ(start.tv_nsec, end.tv_nsec);
-}
-
-TEST(TimeTest, timevalConversions) {
-  timeval start{1234, 5678};  // NOLINT
-  Time time(start);
-  EXPECT_EQ(start.tv_sec, static_cast<long>(time.sec()));
-  EXPECT_EQ(start.tv_usec, time.nsec() / Time::kNSecInUSec);
-  timeval end = time.ToTimeval();
-  EXPECT_EQ(start.tv_sec, end.tv_sec);
-  EXPECT_EQ(start.tv_usec, end.tv_usec);
-}
-
-TEST(TimeDeathTest, ConstructorChecking) {
-  logging::Init();
-  EXPECT_DEATH(
-      {
-        logging::AddImplementation(new util::DeathTestLogImplementation());
-        Time(0, -1);
-      },
-      ".*0 <= nsec\\(-1\\) < 10+ .*");
-  EXPECT_DEATH(
-      {
-        logging::AddImplementation(new util::DeathTestLogImplementation());
-        Time(0, Time::kNSecInSec);
-      },
-      ".*0 <= nsec\\(10+\\) < 10+ .*");
-}
-
-// It's kind of hard not to test Now and SleepFor at the same time.
-TEST(TimeTest, NowAndSleepFor) {
-  // without this, it tends to fail the first time (ends up sleeping for way
-  // longer than it should the second time, where it actually matters)
-  SleepFor(Time(0, Time::kNSecInSec / 10));
-  Time start = Time::Now();
-  static constexpr Time kSleepTime = Time(0, Time::kNSecInSec * 2 / 10);
-  SleepFor(kSleepTime);
-  Time difference = Time::Now() - start;
-  EXPECT_GE(difference, kSleepTime);
-  EXPECT_LT(difference, kSleepTime + Time(0, Time::kNSecInSec / 100));
-}
-
-TEST(TimeTest, AbsoluteSleep) {
-  Time start = Time::Now();
-  SleepFor(Time(0, Time::kNSecInSec / 10));
-  static constexpr Time kSleepTime = Time(0, Time::kNSecInSec * 2 / 10);
-  SleepUntil(start + kSleepTime);
-  Time difference = Time::Now() - start;
-  EXPECT_GE(difference, kSleepTime);
-  EXPECT_LT(difference, kSleepTime + Time(0, Time::kNSecInSec / 100));
-}
-
-TEST(TimeTest, Addition) {
-  Time t(54, 500);
-  EXPECT_EQ(MACRO_DARG(Time(54, 5500)), t + MACRO_DARG(Time(0, 5000)));
-  EXPECT_EQ(MACRO_DARG(Time(56, 500)), t + MACRO_DARG(Time(2, 0)));
-  EXPECT_EQ(MACRO_DARG(Time(57, 6500)), t + MACRO_DARG(Time(3, 6000)));
-  EXPECT_EQ(MACRO_DARG(Time(50, 300)),
-            t + MACRO_DARG(Time(-5, Time::kNSecInSec - 200)));
-  EXPECT_EQ(Time(-46, 500), t + Time(-100, 0));
-  EXPECT_EQ(Time(-47, Time::kNSecInSec - 500),
-            Time(-101, Time::kNSecInSec - 1000) + t);
-}
-TEST(TimeTest, Subtraction) {
-  Time t(54, 500);
-  EXPECT_EQ(MACRO_DARG(Time(54, 300)), t - MACRO_DARG(Time(0, 200)));
-  EXPECT_EQ(MACRO_DARG(Time(42, 500)), t - MACRO_DARG(Time(12, 0)));
-  EXPECT_EQ(MACRO_DARG(Time(50, 100)), t - MACRO_DARG(Time(4, 400)));
-  EXPECT_EQ(MACRO_DARG(Time(53, 600)),
-            t - MACRO_DARG(Time(0, Time::kNSecInSec - 100)));
-  EXPECT_EQ(MACRO_DARG(Time(55, 800)),
-            t - MACRO_DARG(Time(-2, Time::kNSecInSec - 300)));
-  EXPECT_EQ(Time(54, 5500), t - Time(-1, Time::kNSecInSec - 5000));
-  EXPECT_EQ(Time(-50, Time::kNSecInSec - 300),
-            Time(5, 200) - t);
-}
-
-TEST(TimeTest, Multiplication) {
-  Time t(54, Time::kNSecInSec / 3);
-  EXPECT_EQ(MACRO_DARG(Time(108, Time::kNSecInSec / 3 * 2)), t * 2);
-  EXPECT_EQ(MACRO_DARG(Time(271, Time::kNSecInSec / 3 * 2 - 1)), t * 5);
-  EXPECT_EQ(Time(-109, Time::kNSecInSec / 3 + 1), t * -2);
-  EXPECT_EQ(Time(-55, Time::kNSecInSec / 3 * 2 + 1), t * -1);
-  EXPECT_EQ(Time(-218, Time::kNSecInSec / 3 * 2 + 2), (t * -1) * 4);
-}
-TEST(TimeTest, DivisionByInt) {
-  EXPECT_EQ(Time(5, Time::kNSecInSec / 10 * 4 + 50), Time(54, 500) / 10);
-  EXPECT_EQ(Time(2, Time::kNSecInSec / 4 * 3),
-            Time(5, Time::kNSecInSec / 2) / 2);
-  EXPECT_EQ(Time(-3, Time::kNSecInSec / 4 * 3),
-            Time(-5, Time::kNSecInSec / 2) / 2);
-}
-TEST(TimeTest, DivisionByTime) {
-  EXPECT_DOUBLE_EQ(2, Time(10, 0) / Time(5, 0));
-  EXPECT_DOUBLE_EQ(9, Time(27, 0) / Time(3, 0));
-  EXPECT_DOUBLE_EQ(9.25, Time(37, 0) / Time(4, 0));
-  EXPECT_DOUBLE_EQ(5.25, Time(36, Time::kNSecInSec / 4 * 3) / Time(7, 0));
-  EXPECT_DOUBLE_EQ(-5.25, Time(-37, Time::kNSecInSec / 4) / Time(7, 0));
-  EXPECT_DOUBLE_EQ(-5.25, Time(36, Time::kNSecInSec / 4 * 3) / Time(-7, 0));
-}
-
-TEST(TimeTest, Negation) {
-  EXPECT_EQ(Time(-5, 1234), -Time(4, Time::kNSecInSec - 1234));
-  EXPECT_EQ(Time(5, Time::kNSecInSec * 2 / 3 + 1),
-            -Time(-6, Time::kNSecInSec / 3));
-}
-
-TEST(TimeTest, Comparisons) {
-  EXPECT_TRUE(Time(971, 254) > Time(971, 253));
-  EXPECT_TRUE(Time(971, 254) >= Time(971, 253));
-  EXPECT_TRUE(Time(971, 254) < Time(971, 255));
-  EXPECT_TRUE(Time(971, 254) <= Time(971, 255));
-  EXPECT_TRUE(Time(971, 254) >= Time(971, 253));
-  EXPECT_TRUE(Time(971, 254) <= Time(971, 254));
-  EXPECT_TRUE(Time(971, 254) >= Time(971, 254));
-  EXPECT_TRUE(Time(972, 254) > Time(971, 254));
-  EXPECT_TRUE(Time(971, 254) < Time(972, 254));
-
-  EXPECT_TRUE(Time(-971, 254) > Time(-971, 253));
-  EXPECT_TRUE(Time(-971, 254) >= Time(-971, 253));
-  EXPECT_TRUE(Time(-971, 254) < Time(-971, 255));
-  EXPECT_TRUE(Time(-971, 254) <= Time(-971, 255));
-  EXPECT_TRUE(Time(-971, 254) >= Time(-971, 253));
-  EXPECT_TRUE(Time(-971, 254) <= Time(-971, 254));
-  EXPECT_TRUE(Time(-971, 254) >= Time(-971, 254));
-  EXPECT_TRUE(Time(-972, 254) < Time(-971, 254));
-  EXPECT_TRUE(Time(-971, 254) > Time(-972, 254));
-}
-
-TEST(TimeTest, Within) {
-  EXPECT_TRUE(MACRO_DARG(Time(55, 5000).IsWithin(Time(55, 4900), 100)));
-  EXPECT_FALSE(MACRO_DARG(Time(55, 5000).IsWithin(Time(55, 4900), 99)));
-  EXPECT_TRUE(MACRO_DARG(Time(5, 0).IsWithin(Time(4, Time::kNSecInSec - 200),
-                                             250)));
-  EXPECT_TRUE(Time(-5, Time::kNSecInSec - 200).IsWithin(Time(-4, 0), 250));
-  EXPECT_TRUE(Time(-5, 200).IsWithin(Time(-5, 0), 250));
-}
-
-TEST(TimeTest, Modulus) {
-  EXPECT_EQ(MACRO_DARG(Time(0, Time::kNSecInSec / 10 * 2)),
-            MACRO_DARG(Time(50, 0) % (Time::kNSecInSec / 10 * 3)));
-  EXPECT_EQ(Time(-1, Time::kNSecInSec / 10 * 8),
-            Time(-50, 0) % (Time::kNSecInSec / 10 * 3));
-  EXPECT_EQ(Time(-1, Time::kNSecInSec / 10 * 8),
-            Time(-50, 0) % (-Time::kNSecInSec / 10 * 3));
-  EXPECT_EQ(Time(0, Time::kNSecInSec / 10 * 2),
-            Time(50, 0) % (-Time::kNSecInSec / 10 * 3));
-  EXPECT_EQ(Time(1, Time::kNSecInSec / 10),
-            Time(60, Time::kNSecInSec / 10) % (Time::kNSecInSec / 10 * 12));
-}
-
-TEST(TimeTest, InSeconds) {
-  EXPECT_EQ(MACRO_DARG(Time(2, Time::kNSecInSec / 100 * 55 - 1)),
-            Time::InSeconds(2.55));
-  EXPECT_EQ(MACRO_DARG(Time(-3, Time::kNSecInSec / 100 * 45)),
-            Time::InSeconds(-2.55));
-}
-
-TEST(TimeTest, ToSeconds) {
-  EXPECT_DOUBLE_EQ(13.23, Time::InSeconds(13.23).ToSeconds());
-  EXPECT_NEAR(-13.23, Time::InSeconds(-13.23).ToSeconds(),
-              1.0 / Time::kNSecInSec * 2);
-}
-
-TEST(TimeTest, InMS) {
-  Time t = Time::InMS(254971);
-  EXPECT_EQ(254, t.sec());
-  EXPECT_EQ(971000000, t.nsec());
-
-  Time t2 = Time::InMS(-254971);
-  EXPECT_EQ(-255, t2.sec());
-  EXPECT_EQ(Time::kNSecInSec - 971000000, t2.nsec());
-
-  Time t3 = Time::InMS(-1000);
-  EXPECT_EQ(-1, t3.sec());
-  EXPECT_EQ(0, t3.nsec());
-
-  Time t4 = Time::InMS(1000);
-  EXPECT_EQ(1, t4.sec());
-  EXPECT_EQ(0, t4.nsec());
-
-  Time t5 = Time::InMS(1001);
-  EXPECT_EQ(1, t5.sec());
-  EXPECT_EQ(Time::kNSecInMSec, t5.nsec());
-
-  Time t6 = Time::InMS(-1001);
-  EXPECT_EQ(-2, t6.sec());
-  EXPECT_EQ(Time::kNSecInSec - Time::kNSecInMSec, t6.nsec());
-
-  Time t7 = Time::InMS(-999);
-  EXPECT_EQ(-1, t7.sec());
-  EXPECT_EQ(Time::kNSecInMSec, t7.nsec());
-
-  Time t8 = Time::InMS(999);
-  EXPECT_EQ(0, t8.sec());
-  EXPECT_EQ(Time::kNSecInSec - Time::kNSecInMSec, t8.nsec());
-}
-
-TEST(TimeTest, ToMSec) {
-  EXPECT_EQ(254971, Time(254, 971000000).ToMSec());
-  EXPECT_EQ(-254971, Time(-255, Time::kNSecInSec - 971000000).ToMSec());
-}
-
-TEST(TimeTest, InNS) {
-  Time t = Time::InNS(static_cast<int64_t>(973254111971ll));
-  EXPECT_EQ(973, t.sec());
-  EXPECT_EQ(254111971, t.nsec());
-
-  Time t2 = Time::InNS(static_cast<int64_t>(-973254111971ll));
-  EXPECT_EQ(-974, t2.sec());
-  EXPECT_EQ(Time::kNSecInSec - 254111971, t2.nsec());
-}
-
-TEST(TimeTest, InUS) {
-  Time t = Time::InUS(254111971);
-  EXPECT_EQ(254, t.sec());
-  EXPECT_EQ(111971000, t.nsec());
-
-  Time t2 = Time::InUS(-254111971);
-  EXPECT_EQ(-255, t2.sec());
-  EXPECT_EQ(Time::kNSecInSec - 111971000, t2.nsec());
-}
-
-TEST(TimeTest, ToUSec) {
-  EXPECT_EQ(254000971, Time(254, 971000).ToUSec());
-  EXPECT_EQ(-254000971, Time(-255, Time::kNSecInSec - 971000).ToUSec());
-}
-
-TEST(TimeTest, Abs) {
-  EXPECT_EQ(MACRO_DARG(Time(971, 1114)), MACRO_DARG(Time(971, 1114).abs()));
-  EXPECT_EQ(MACRO_DARG(Time(253, Time::kNSecInSec * 0.3)),
-            MACRO_DARG(Time(-254, Time::kNSecInSec * 0.7).abs()));
-  EXPECT_EQ(MACRO_DARG(-Time(-971, 973).ToNSec()),
-            MACRO_DARG(Time(970, Time::kNSecInSec - 973).ToNSec()));
-}
 
 TEST(TimeTest, FromRate) {
-  EXPECT_EQ(::std::chrono::milliseconds(10), Time::FromRate(100));
+  EXPECT_EQ(::std::chrono::milliseconds(10), FromRate(100));
 }
 
 // Test the monotonic_clock and sleep_until functions.
diff --git a/aos/common/util/log_interval.h b/aos/common/util/log_interval.h
index 3a7a85f..8823341 100644
--- a/aos/common/util/log_interval.h
+++ b/aos/common/util/log_interval.h
@@ -12,7 +12,7 @@
 // A class to help with logging things that happen a lot only occasionally.
 //
 // Intended use {
-//   static LogInterval interval(::aos::time::Time::InSeconds(0.2));
+//   static LogInterval interval(::std::chrono::millseconds(200));
 //
 //   if (WantToLog()) {
 //     interval.WantToLog();
diff --git a/aos/common/util/phased_loop.cc b/aos/common/util/phased_loop.cc
index 9c81ffb..bea262d 100644
--- a/aos/common/util/phased_loop.cc
+++ b/aos/common/util/phased_loop.cc
@@ -3,13 +3,6 @@
 namespace aos {
 namespace time {
 
-void PhasedLoopXMS(int ms, int offset) {
-  const Time frequency = Time::InMS(ms);
-  SleepUntil((Time::Now() / static_cast<int32_t>(frequency.ToNSec())) *
-             static_cast<int32_t>(frequency.ToNSec()) +
-             frequency + Time::InUS(offset));
-}
-
 int PhasedLoop::Iterate(const monotonic_clock::time_point now) {
   const monotonic_clock::time_point next_time =
       monotonic_clock::time_point(
diff --git a/aos/common/util/phased_loop.h b/aos/common/util/phased_loop.h
index 7614ed2..fbfe954 100644
--- a/aos/common/util/phased_loop.h
+++ b/aos/common/util/phased_loop.h
@@ -8,11 +8,6 @@
 namespace aos {
 namespace time {
 
-// Will not be accurate if ms isn't a factor of 1000.
-// offset is in us.
-// DEPRECATED(Brian): Use PhasedLoop instead.
-void PhasedLoopXMS(int ms, int offset);
-
 // Handles sleeping until a fixed offset from some time interval.
 class PhasedLoop {
  public:
@@ -21,7 +16,7 @@
   //   1.1s
   //   ...
   //   10000.1s
-  // offset must be >= Time::kZero and < interval.
+  // offset must be >= chrono::seconds(0) and < interval.
   PhasedLoop(
       const monotonic_clock::duration interval,
       const monotonic_clock::duration offset = monotonic_clock::duration(0))
diff --git a/aos/linux_code/ipc_lib/ipc_comparison.cc b/aos/linux_code/ipc_lib/ipc_comparison.cc
index 73c0f9b..11373a5 100644
--- a/aos/linux_code/ipc_lib/ipc_comparison.cc
+++ b/aos/linux_code/ipc_lib/ipc_comparison.cc
@@ -1,31 +1,32 @@
 #include "third_party/gflags/include/gflags/gflags.h"
 
-#include <stdint.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <pthread.h>
+#include <fcntl.h>
+#include <mqueue.h>
 #include <netinet/in.h>
 #include <netinet/tcp.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <stdint.h>
+#include <sys/eventfd.h>
 #include <sys/msg.h>
 #include <sys/sem.h>
-#include <sys/eventfd.h>
-#include <semaphore.h>
-#include <mqueue.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/un.h>
 
-#include <thread>
+#include <atomic>
+#include <chrono>
 #include <memory>
 #include <string>
-#include <atomic>
+#include <thread>
 
-#include "aos/common/logging/logging.h"
-#include "aos/common/logging/implementations.h"
-#include "aos/common/time.h"
-#include "aos/common/mutex.h"
-#include "aos/common/event.h"
 #include "aos/common/condition.h"
+#include "aos/common/event.h"
+#include "aos/common/logging/implementations.h"
+#include "aos/common/logging/logging.h"
+#include "aos/common/mutex.h"
+#include "aos/common/time.h"
 #include "aos/linux_code/init.h"
 #include "aos/linux_code/ipc_lib/queue.h"
 
@@ -40,6 +41,8 @@
 
 namespace aos {
 
+namespace chrono = ::std::chrono;
+
 // A generic interface for an object which can send some data to another thread
 // and back.
 //
@@ -882,7 +885,7 @@
     ping_ponger->Ping();
   }
 
-  const time::Time start = time::Time::Now();
+  const monotonic_clock::time_point start = monotonic_clock::now();
 
   for (int32_t i = 0; i < FLAGS_messages; ++i) {
     PingPongerInterface::Data *to_send = ping_ponger->PingData();
@@ -893,7 +896,7 @@
     }
   }
 
-  const time::Time end = time::Time::Now();
+  const monotonic_clock::time_point end = monotonic_clock::now();
 
   // Try to make sure the server thread gets past its check of done so our
   // Ping() down below doesn't hang. Kind of lame, but doing better would
@@ -906,13 +909,14 @@
   server.join();
 
   LOG(INFO, "Took %f seconds to send %" PRId32 " messages\n",
-      (end - start).ToSeconds(), FLAGS_messages);
-  const time::Time per_message = (end - start) / FLAGS_messages;
-  if (per_message.sec() > 0) {
+      chrono::duration_cast<chrono::duration<double>>(end - start).count(),
+      FLAGS_messages);
+  const chrono::nanoseconds per_message = (end - start) / FLAGS_messages;
+  if (per_message >= chrono::seconds(1)) {
     LOG(INFO, "More than 1 second per message ?!?\n");
   } else {
     LOG(INFO, "That is %" PRId32 " nanoseconds per message\n",
-        per_message.nsec());
+        static_cast<int>(per_message.count()));
   }
 
   return 0;
diff --git a/aos/linux_code/ipc_lib/ipc_stress_test.cc b/aos/linux_code/ipc_lib/ipc_stress_test.cc
index 2ca4628..1b4d22e 100644
--- a/aos/linux_code/ipc_lib/ipc_stress_test.cc
+++ b/aos/linux_code/ipc_lib/ipc_stress_test.cc
@@ -1,21 +1,22 @@
-#include <stdio.h>
-#include <unistd.h>
 #include <errno.h>
+#include <libgen.h>
+#include <stdio.h>
 #include <string.h>
 #include <sys/types.h>
 #include <sys/wait.h>
-#include <libgen.h>
+#include <unistd.h>
 
+#include <chrono>
 #include <string>
 
+#include "aos/common/die.h"
+#include "aos/common/libc/aos_strsignal.h"
+#include "aos/common/libc/dirname.h"
+#include "aos/common/logging/logging.h"
+#include "aos/common/mutex.h"
 #include "aos/common/time.h"
 #include "aos/common/type_traits.h"
-#include "aos/common/mutex.h"
 #include "aos/linux_code/ipc_lib/core_lib.h"
-#include "aos/common/die.h"
-#include "aos/common/libc/dirname.h"
-#include "aos/common/libc/aos_strsignal.h"
-#include "aos/common/logging/logging.h"
 #include "aos/testing/test_shm.h"
 
 // This runs all of the IPC-related tests in a bunch of parallel processes for a
@@ -34,6 +35,8 @@
 
 namespace aos {
 
+namespace chrono = ::std::chrono;
+
 // Each test is represented by the name of the test binary and then any
 // arguments to pass to it.
 // Using --gtest_filter is a bad idea because it seems to result in a lot of
@@ -55,12 +58,12 @@
 // How many test processes to run at a time.
 static const int kTesters = 100;
 // How long to test for.
-static constexpr time::Time kTestTime = time::Time::InSeconds(30);
+static constexpr monotonic_clock::duration kTestTime = chrono::seconds(30);
 
 // The structure that gets put into shared memory and then referenced by all of
 // the child processes.
 struct Shared {
-  Shared(const time::Time &stop_time)
+  Shared(const monotonic_clock::time_point stop_time)
     : stop_time(stop_time), total_iterations(0) {}
 
   // Synchronizes access to stdout/stderr to avoid interleaving failure
@@ -68,7 +71,7 @@
   Mutex output_mutex;
 
   // When to stop.
-  time::Time stop_time;
+  monotonic_clock::time_point stop_time;
 
   // The total number of iterations. Updated by each child as it finishes.
   int total_iterations;
@@ -128,7 +131,7 @@
   // same test at the same time for the whole test.
   const char *(*test)[kTestMaxArgs] = &kTests[getpid() % kTestsLength];
   int pipes[2];
-  while (time::Time::Now() < shared->stop_time) {
+  while (monotonic_clock::now() < shared->stop_time) {
     if (pipe(pipes) == -1) {
       PDie("pipe(%p) failed", &pipes);
     }
@@ -213,7 +216,7 @@
   ::aos::testing::TestSharedMemory my_shm_;
 
   Shared *shared = static_cast<Shared *>(shm_malloc(sizeof(Shared)));
-  new (shared) Shared(time::Time::Now() + kTestTime);
+  new (shared) Shared(monotonic_clock::now() + kTestTime);
 
   if (asprintf(const_cast<char **>(&shared->path),
                "%s/../tests", ::aos::libc::Dirname(argv[0]).c_str()) == -1) {
diff --git a/aos/linux_code/ipc_lib/raw_queue_test.cc b/aos/linux_code/ipc_lib/raw_queue_test.cc
index ec07a0b..0c341e3 100644
--- a/aos/linux_code/ipc_lib/raw_queue_test.cc
+++ b/aos/linux_code/ipc_lib/raw_queue_test.cc
@@ -4,6 +4,7 @@
 #include <sys/mman.h>
 #include <inttypes.h>
 
+#include <chrono>
 #include <ostream>
 #include <memory>
 #include <map>
@@ -28,6 +29,9 @@
 namespace aos {
 namespace testing {
 
+namespace chrono = ::std::chrono;
+namespace this_thread = ::std::this_thread;
+
 // The same constant from queue.cc. This will have to be updated if that one is.
 const int kExtraMessages = 20;
 
@@ -70,7 +74,7 @@
   };
   template<typename T>
   static void Hangs_(FunctionToCall<T> *const to_call) {
-    time::SleepFor(time::Time::InSeconds(0.01));
+    this_thread::sleep_for(chrono::milliseconds(10));
     ASSERT_EQ(1, futex_set(&to_call->started));
     to_call->result = ResultType::Called;
     to_call->function(to_call->arg, const_cast<char *>(to_call->failure));
@@ -78,9 +82,9 @@
   }
 
   // How long until a function is considered to have hung.
-  static constexpr time::Time kHangTime = time::Time::InSeconds(0.09);
+  static constexpr chrono::nanoseconds kHangTime = chrono::milliseconds(90);
   // How long to sleep after forking (for debugging).
-  static constexpr time::Time kForkSleep = time::Time::InSeconds(0);
+  static constexpr chrono::nanoseconds kForkSleep = chrono::milliseconds(0);
 
   // Represents a process that has been forked off. The destructor kills the
   // process and wait(2)s for it.
@@ -118,8 +122,19 @@
     enum class JoinResult {
       Finished, Hung, Error
     };
-    JoinResult Join(time::Time timeout = kHangTime) {
-      timespec done_timeout = (kForkSleep + timeout).ToTimespec();
+    JoinResult Join(chrono::nanoseconds timeout = kHangTime) {
+      struct timespec done_timeout;
+      {
+        auto full_timeout = kForkSleep + timeout;
+        ::std::chrono::seconds sec =
+            ::std::chrono::duration_cast<::std::chrono::seconds>(full_timeout);
+        ::std::chrono::nanoseconds nsec =
+            ::std::chrono::duration_cast<::std::chrono::nanoseconds>(
+                full_timeout - sec);
+        done_timeout.tv_sec = sec.count();
+        done_timeout.tv_nsec = nsec.count();
+      }
+
       switch (futex_wait_timeout(done_, &done_timeout)) {
         case 2:
           return JoinResult::Hung;
@@ -172,11 +187,10 @@
     const pid_t pid = fork();
     switch (pid) {
       case 0:  // child
-        if (kForkSleep != time::Time(0, 0)) {
-          LOG(INFO, "pid %jd sleeping for %ds%dns\n",
-              static_cast<intmax_t>(getpid()),
-              kForkSleep.sec(), kForkSleep.nsec());
-          time::SleepFor(kForkSleep);
+        if (kForkSleep != chrono::milliseconds(0)) {
+          LOG(INFO, "pid %jd sleeping for %" PRId64 "ns\n",
+              static_cast<intmax_t>(getpid()), kForkSleep.count());
+          this_thread::sleep_for(kForkSleep);
         }
         ::aos::testing::PreventExit();
         function(arg);
@@ -325,8 +339,8 @@
 char *RawQueueTest::fatal_failure;
 std::map<RawQueueTest::ChildID, RawQueueTest::ForkedProcess *>
     RawQueueTest::children_;
-constexpr time::Time RawQueueTest::kHangTime;
-constexpr time::Time RawQueueTest::kForkSleep;
+constexpr chrono::nanoseconds RawQueueTest::kHangTime;
+constexpr chrono::nanoseconds RawQueueTest::kForkSleep;
 
 typedef RawQueueTest RawQueueDeathTest;
 
diff --git a/aos/linux_code/ipc_lib/shared_mem_types.h b/aos/linux_code/ipc_lib/shared_mem_types.h
index 81fab60..07bb60e 100644
--- a/aos/linux_code/ipc_lib/shared_mem_types.h
+++ b/aos/linux_code/ipc_lib/shared_mem_types.h
@@ -28,12 +28,12 @@
   // the owner sets as soon as it finishes setting stuff up.
   aos_condition creation_condition;
 
-  // An offset from CLOCK_REALTIME to times for all the code.
+  // An offset from CLOCK_MONOTONIC to times for all the code in nanoseconds.
   // This is currently only set to non-zero by the log replay code.
   // There is no synchronization on this to avoid the overhead because it is
   // only updated with proper memory barriers when only a single task is
   // running.
-  struct timespec time_offset;
+  int64_t time_offset;
 
   struct aos_mutex msg_alloc_lock;
   void *msg_alloc;
diff --git a/aos/linux_code/starter/starter.cc b/aos/linux_code/starter/starter.cc
index 86d601e..57d90dd 100644
--- a/aos/linux_code/starter/starter.cc
+++ b/aos/linux_code/starter/starter.cc
@@ -55,6 +55,8 @@
 namespace aos {
 namespace starter {
 
+namespace chrono = ::std::chrono;
+
 // TODO(brians): split out the c++ libevent wrapper stuff into its own file(s)
 class EventBaseDeleter {
  public:
@@ -332,12 +334,21 @@
 }
 
 // Will call callback(arg) after time.
-void Timeout(time::Time time, void (*callback)(int, short, void *), void *arg) {
+void Timeout(monotonic_clock::duration time,
+             void (*callback)(int, short, void *), void *arg) {
   EventUniquePtr timeout(evtimer_new(libevent_base.get(), callback, arg));
-  struct timeval time_timeval = time.ToTimeval();
+  struct timeval time_timeval;
+  {
+    ::std::chrono::seconds sec =
+        ::std::chrono::duration_cast<::std::chrono::seconds>(time);
+    ::std::chrono::microseconds usec =
+        ::std::chrono::duration_cast<::std::chrono::microseconds>(time - sec);
+    time_timeval.tv_sec = sec.count();
+    time_timeval.tv_usec = usec.count();
+  }
   if (evtimer_add(timeout.release(), &time_timeval) != 0) {
-    LOG(FATAL, "evtimer_add(%p, %p) failed\n",
-        timeout.release(), &time_timeval);
+    LOG(FATAL, "evtimer_add(%p, %p) failed\n", timeout.release(),
+        &time_timeval);
   }
 }
 
@@ -383,11 +394,11 @@
   // restarted.
   void ProcessDied() {
     pid_ = -1;
-    restarts_.push(time::Time::Now());
+    restarts_.push(monotonic_clock::now());
     if (restarts_.size() > kMaxRestartsNumber) {
-      time::Time oldest = restarts_.front();
+      monotonic_clock::time_point oldest = restarts_.front();
       restarts_.pop();
-      if ((time::Time::Now() - oldest) <= kMaxRestartsTime) {
+      if (monotonic_clock::now() <= kMaxRestartsTime + oldest) {
         LOG(WARNING, "process %s getting restarted too often\n", name());
         Timeout(kResumeWait, StaticStart, this);
         return;
@@ -408,19 +419,20 @@
   };
 
   // How long to wait for a child to die nicely.
-  static constexpr time::Time kProcessDieTime = time::Time::InSeconds(2);
+  static constexpr chrono::nanoseconds kProcessDieTime = chrono::seconds(2);
 
   // How long to wait after the file is modified to restart it.
   // This is important because some programs like modifying the binaries by
   // writing them in little bits, which results in attempting to start partial
   // binaries without this.
-  static constexpr time::Time kRestartWaitTime = time::Time::InSeconds(1.5);
+  static constexpr chrono::nanoseconds kRestartWaitTime =
+      chrono::milliseconds(1500);
 
   // Only kMaxRestartsNumber restarts will be allowed in kMaxRestartsTime.
-  static constexpr time::Time kMaxRestartsTime = time::Time::InSeconds(4);
+  static constexpr chrono::nanoseconds kMaxRestartsTime = chrono::seconds(4);
   static const size_t kMaxRestartsNumber = 3;
   // How long to wait if it gets restarted too many times.
-  static constexpr time::Time kResumeWait = time::Time::InSeconds(5);
+  static constexpr chrono::nanoseconds kResumeWait = chrono::seconds(5);
 
   static void StaticFileModified(void *self) {
     static_cast<Child *>(self)->FileModified();
@@ -428,11 +440,21 @@
 
   void FileModified() {
     LOG(DEBUG, "file for %s modified\n", name());
-    struct timeval restart_time_timeval = kRestartWaitTime.ToTimeval();
+    struct timeval restart_time_timeval;
+    {
+      ::std::chrono::seconds sec =
+          ::std::chrono::duration_cast<::std::chrono::seconds>(
+              kRestartWaitTime);
+      ::std::chrono::microseconds usec =
+          ::std::chrono::duration_cast<::std::chrono::microseconds>(
+              kRestartWaitTime - sec);
+      restart_time_timeval.tv_sec = sec.count();
+      restart_time_timeval.tv_usec = usec.count();
+    }
     // This will reset the timeout again if it hasn't run yet.
     if (evtimer_add(restart_timeout.get(), &restart_time_timeval) != 0) {
-      LOG(FATAL, "evtimer_add(%p, %p) failed\n",
-          restart_timeout.get(), &restart_time_timeval);
+      LOG(FATAL, "evtimer_add(%p, %p) failed\n", restart_timeout.get(),
+          &restart_time_timeval);
     }
     waiting_to_restart.insert(this);
   }
@@ -551,7 +573,8 @@
   }
 
   // A history of the times that this process has been restarted.
-  std::queue<time::Time, std::list<time::Time>> restarts_;
+  std::queue<monotonic_clock::time_point,
+             std::list<monotonic_clock::time_point>> restarts_;
 
   // The currently running child's PID or NULL.
   pid_t pid_;
@@ -581,10 +604,10 @@
   DISALLOW_COPY_AND_ASSIGN(Child);
 };
 
-constexpr time::Time Child::kProcessDieTime;
-constexpr time::Time Child::kRestartWaitTime;
-constexpr time::Time Child::kMaxRestartsTime;
-constexpr time::Time Child::kResumeWait;
+constexpr chrono::nanoseconds Child::kProcessDieTime;
+constexpr chrono::nanoseconds Child::kRestartWaitTime;
+constexpr chrono::nanoseconds Child::kMaxRestartsTime;
+constexpr chrono::nanoseconds Child::kResumeWait;
 
 EventUniquePtr Child::restart_timeout;
 ::std::set<Child *> Child::waiting_to_restart;
@@ -592,8 +615,8 @@
 // Kills off the entire process group (including ourself).
 void KillChildren(bool try_nice) {
   if (try_nice) {
-    static const int kNiceStopSignal = SIGTERM;
-    static const time::Time kNiceWaitTime = time::Time::InSeconds(1);
+    static constexpr int kNiceStopSignal = SIGTERM;
+    static constexpr auto kNiceWaitTime = chrono::seconds(1);
 
     // Make sure that we don't just nicely stop ourself...
     sigset_t mask;
@@ -604,7 +627,7 @@
     kill(-getpid(), kNiceStopSignal);
 
     fflush(NULL);
-    time::SleepFor(kNiceWaitTime);
+    ::std::this_thread::sleep_for(kNiceWaitTime);
   }
 
   // Send SIGKILL to our whole process group, which will forcibly terminate any
diff --git a/aos/vision/events/epoll_events.cc b/aos/vision/events/epoll_events.cc
index 56b22e2..aaecdbf 100644
--- a/aos/vision/events/epoll_events.cc
+++ b/aos/vision/events/epoll_events.cc
@@ -57,10 +57,10 @@
  private:
   // Calculates the new timeout value to pass to epoll_wait.
   int CalculateTimeout() {
-    const ::aos::time::Time now = ::aos::time::Time::Now();
+    const monotonic_clock::time_point monotonic_now = monotonic_clock::now();
     int r = -1;
     for (EpollWait *c : waits_) {
-      const int new_timeout = c->Recalculate(now);
+      const int new_timeout = c->Recalculate(monotonic_now);
       if (new_timeout >= 0) {
         if (r < 0 || new_timeout < r) {
           r = new_timeout;
diff --git a/aos/vision/events/epoll_events.h b/aos/vision/events/epoll_events.h
index f032e61..1cb6842 100644
--- a/aos/vision/events/epoll_events.h
+++ b/aos/vision/events/epoll_events.h
@@ -25,7 +25,7 @@
 
   // Sets this wait to end at new_time.
   // A negative new_time disables this wait.
-  void SetTime(const ::aos::time::Time &new_time) { time_ = new_time; }
+  void SetTime(const monotonic_clock::time_point new_time) { time_ = new_time; }
 
  private:
   // Calculates how long to wait starting at now and calls Done() if
@@ -33,21 +33,23 @@
   // Returns the number of milliseconds from now that this event will expire in.
   // Returns -1 if this wait is never going to expire.
   // Returns INT_MAX if this wait expires in longer than that.
-  int Recalculate(const ::aos::time::Time &now) {
-    if (time_ < ::aos::time::Time::kZero) return -1;
+  int Recalculate(const monotonic_clock::time_point now) {
+    if (time_ < monotonic_clock::epoch()) return -1;
     if (time_ <= now) {
       Done();
-      time_ = ::aos::time::Time(-1, 0);
+      time_ = monotonic_clock::time_point(::std::chrono::seconds(-1));
       return -1;
     }
-    if (time_ - now > ::aos::time::Time::InMS(INT_MAX)) {
+    if (time_ - now > ::std::chrono::milliseconds(INT_MAX)) {
       return INT_MAX;
     } else {
-      return (time_ - now).ToMSec();
+      return ::std::chrono::duration_cast<::std::chrono::milliseconds>(time_ -
+                                                                       now)
+          .count();
     }
   }
 
-  ::aos::time::Time time_ = ::aos::time::Time::kZero;
+  ::aos::monotonic_clock::time_point time_ = ::aos::monotonic_clock::epoch();
 
   friend class EpollLoop;
 };