diff --git a/dune/common/test/CMakeLists.txt b/dune/common/test/CMakeLists.txt
index a39fd5f5e4cecb3965e8cd59db725657253faa90..045c847e1592eeafe7fb8d22bffb9c78519b106b 100644
--- a/dune/common/test/CMakeLists.txt
+++ b/dune/common/test/CMakeLists.txt
@@ -348,6 +348,9 @@ dune_add_test(SOURCES typeutilitytest.cc
 dune_add_test(SOURCES typelisttest.cc
               LABELS quick)
 
+dune_add_test(SOURCES timertest.cc
+              LABELS quick)
+
 dune_add_test(SOURCES utilitytest.cc
               LABELS quick)
 
diff --git a/dune/common/test/timertest.cc b/dune/common/test/timertest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..5cfc821ea44107e7d6d2f5c9034c7c0b5dc34834
--- /dev/null
+++ b/dune/common/test/timertest.cc
@@ -0,0 +1,73 @@
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+// SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root
+// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
+
+#include <chrono>
+#include <thread>
+
+#include <dune/common/timer.hh>
+
+#include <dune/common/test/testsuite.hh>
+
+int
+main()
+{
+  Dune::TestSuite suite;
+
+  using clock = std::chrono::high_resolution_clock;
+  using namespace std::chrono_literals;
+  Dune::Timer top_timer(false);
+  auto top_chrono_start = clock::now();
+  std::this_thread::sleep_for(10ms);
+  top_timer.start();
+
+  Dune::Timer loop_timer;
+  for (std::size_t i = 0; i != 5; ++i) {
+    { // let chrono timer run for longer time
+      auto chrono_start = clock::now();
+      loop_timer.start();
+      std::this_thread::sleep_for(10ms);
+      loop_timer.stop();
+      double dune_elapsed = loop_timer.lastElapsed();
+      std::this_thread::sleep_for(10ms);
+      auto chrono_elapsed = clock::now() - chrono_start;
+
+      std::this_thread::sleep_for(10ms);
+      suite.check(dune_elapsed == loop_timer.lastElapsed())
+        << "Elapsed time is not the same as when timer is stop";
+      suite.check(dune_elapsed < (chrono_elapsed / 1.0s))
+        << "Dune timer " << dune_elapsed << "s takes more time than chrono timer "
+        << (chrono_elapsed / 1.0s) << "s";
+    }
+
+    { // let dune timer run for longer time
+      loop_timer.start();
+      auto chrono_start = clock::now();
+      std::this_thread::sleep_for(10ms);
+      auto chrono_elapsed = clock::now() - chrono_start;
+      std::this_thread::sleep_for(10ms);
+      loop_timer.stop();
+      double dune_elapsed = loop_timer.lastElapsed();
+
+      std::this_thread::sleep_for(10ms);
+      suite.check(dune_elapsed == loop_timer.lastElapsed())
+        << "Elapsed time is not the same as when timer is stop";
+      suite.check(dune_elapsed > (chrono_elapsed / 1.0s))
+        << "Dune timer " << dune_elapsed << "s takes less time than chrono timer "
+        << (chrono_elapsed / 1.0s) << "s";
+    }
+  }
+
+  double top_dune_elapsed = top_timer.stop();
+  std::this_thread::sleep_for(10ms);
+  auto top_chrono_elapsed = clock::now() - top_chrono_start;
+
+  suite.check(top_dune_elapsed < (top_chrono_elapsed / 1.0s))
+    << "Top Dune timer " << top_dune_elapsed << "s takes less time than Top chrono timer "
+    << (top_chrono_elapsed / 1.0s) << "s";
+
+  suite.check(top_dune_elapsed > loop_timer.elapsed())
+    << "Top Dune timer " << top_dune_elapsed << "s takes less time than Loop Dune timer "
+    << loop_timer.elapsed() << "s";
+}
diff --git a/dune/common/timer.hh b/dune/common/timer.hh
index a5349faa75e5d38fe63d0980519d153b6d21333f..aa34d7b0db1a5e001887566ac405f2d9854cf7f6 100644
--- a/dune/common/timer.hh
+++ b/dune/common/timer.hh
@@ -5,13 +5,7 @@
 #ifndef DUNE_TIMER_HH
 #define DUNE_TIMER_HH
 
-#ifndef TIMER_USE_STD_CLOCK
-// headers for std::chrono
 #include <chrono>
-#else
-// headers for std::clock
-#include <ctime>
-#endif
 
 namespace Dune {
 
@@ -26,21 +20,17 @@ namespace Dune {
 
   /** \brief A simple stop watch
 
-     This class reports the elapsed user-time, i.e. time spent computing,
-     after the last call to Timer::reset(). The results are seconds and
-     fractional seconds. Note that the resolution of the timing depends
-     on your OS kernel which should be somewhere in the millisecond range.
-
-     The class is basically a wrapper for the libc-function getrusage()
-
-     \warning In a multi-threading situation, this class does NOT return wall-time!
-     Instead, the run time for all threads will be added up.
-     For example, if you have four threads running in parallel taking one second each,
-     then the Timer class will return an elapsed time of four seconds.
+     This class reports the elapsed real time, i.e. time elapsed
+     after Timer::reset(). It does not measure the time spent computing,
+     i.e. time spend in concurrent threads is not added up while
+     time measurements include the time elapsed while sleeping.
 
+     The class is basically a wrapper around std::chrono::high_resolution_clock::now().
    */
   class Timer
   {
+    using Clock = std::chrono::high_resolution_clock;
+    using Units = std::chrono::duration<double>; // seconds stored as double
   public:
 
     /** \brief A new timer, create and reset
@@ -56,9 +46,9 @@ namespace Dune {
     //! Reset timer while keeping the running/stopped state
     void reset() noexcept
     {
-      sumElapsed_ = 0.0;
-      storedLastElapsed_ = 0.0;
-      rawReset();
+      sumElapsed_ = std::chrono::seconds{0};
+      storedLastElapsed_ = std::chrono::seconds{0};
+      cstart = Clock::now();
     }
 
 
@@ -67,7 +57,7 @@ namespace Dune {
     {
       if (not (isRunning_))
       {
-        rawReset();
+        cstart = Clock::now();
         isRunning_ = true;
       }
     }
@@ -76,33 +66,22 @@ namespace Dune {
     //! Get elapsed user-time from last reset until now/last stop in seconds.
     double elapsed () const noexcept
     {
-      // if timer is running add the time elapsed since last start to sum
-      if (isRunning_)
-        return sumElapsed_ + lastElapsed();
-
-      return sumElapsed_;
+      return durationCast(rawElapsed());
     }
 
-
     //! Get elapsed user-time from last start until now/last stop in seconds.
     double lastElapsed () const noexcept
     {
-      // if timer is running return the current value
-      if (isRunning_)
-        return rawElapsed();
-
-      // if timer is not running return stored value from last run
-      return storedLastElapsed_;
+      return durationCast(rawLastElapsed());
     }
 
-
     //! Stop the timer and return elapsed().
     double stop() noexcept
     {
       if (isRunning_)
       {
         // update storedLastElapsed_ and  sumElapsed_ and stop timer
-        storedLastElapsed_ = lastElapsed();
+        storedLastElapsed_ = rawLastElapsed();
         sumElapsed_ += storedLastElapsed_;
         isRunning_ = false;
       }
@@ -113,37 +92,34 @@ namespace Dune {
   private:
 
     bool isRunning_;
-    double sumElapsed_;
-    double storedLastElapsed_;
+    Clock::duration sumElapsed_;
+    Clock::duration storedLastElapsed_;
 
-
-#ifdef TIMER_USE_STD_CLOCK
-    void rawReset() noexcept
+    Clock::duration rawElapsed () const noexcept
     {
-      cstart = std::clock();
-    }
+      // if timer is running add the time elapsed since last start to sum
+      if (isRunning_)
+        return sumElapsed_ + rawLastElapsed();
 
-    double rawElapsed () const noexcept
-    {
-      return (std::clock()-cstart) / static_cast<double>(CLOCKS_PER_SEC);
+      return sumElapsed_;
     }
 
-    std::clock_t cstart;
-#else
-    void rawReset() noexcept
+    //! Get elapsed user-time from last start until now/last stop in seconds.
+    Clock::duration rawLastElapsed () const noexcept
     {
-      cstart = std::chrono::high_resolution_clock::now();
+      // if timer is running return the current value
+      if (isRunning_)
+        return Clock::now() - cstart;
+
+      // if timer is not running return stored value from last run
+      return storedLastElapsed_;
     }
 
-    double rawElapsed () const noexcept
-    {
-      std::chrono::high_resolution_clock::time_point now = std::chrono::high_resolution_clock::now();
-      std::chrono::duration<double> time_span = std::chrono::duration_cast<std::chrono::duration<double> >(now - cstart);
-      return time_span.count();
+    double durationCast(Clock::duration duration) const noexcept {
+      return std::chrono::duration_cast<Units>(duration).count();
     }
 
-    std::chrono::high_resolution_clock::time_point cstart;
-#endif
+    Clock::time_point cstart;
   }; // end class Timer
 
   /** @} end documentation */