DEV Community

Cover image for Building an extremely accurate UTC clock on the web (without trusting the client clock)
Marco Colli
Marco Colli

Posted on

Building an extremely accurate UTC clock on the web (without trusting the client clock)

Displaying the current UTC time in a browser looks trivial, until you care about accuracy:

  • Client clocks drift and they are not always a reliable source of information.
  • Tabs throttle timers.
  • Networks add latency.

Overview

In this post we’ll present a design that:

  1. fetches authoritative time from your server (not Date.now())
  2. uses performance.now() to track elapsed time with a monotonic clock
  3. renders instantly and smoothly via requestAnimationFrame() (no setInterval())
  4. compensates for network latency
  5. handles the real‑world details that make the difference between “pretty good” and “rock solid”.

The algorithm

  1. Sync: Fetch the server’s current UTC.
  2. Adjust for latency: Estimate one way latency (≈ RTT/2).
  3. Save a local baseline: Record start = performance.now() at the moment the response arrives.
  4. Simulate time: At any later instant, compute
   estimated_time = server_utc_at_response + one_way_latency + (performance.now() - start)
Enter fullscreen mode Exit fullscreen mode
  1. Render: Use requestAnimationFrame(update) to reflect the current second, updating the DOM only when the displayed second changes.

This yields instant, smooth display with low resource usage (low CPU and network usage). It also gives an exact time with high accuracy (± a few ms).

Tips

  • When you need to measure a time difference (e.g. how much time has elapsed from a certain instant) use performance.now() instead of Date.now(). It is more accurate and a change in the system clock doesn't affect it.
  • A very accurate Round Trip Time (RTT) can be estimated using a PerformanceObserver. When you need to measure the RTT of the HTTP request don't use a time difference calculated in your code (e.g. timeRequestEnd - timeRequestStart): that would include some other time that is not relevant in this specific case (like DNS time, connection time, computation time, etc.). Use a PerformanceObserver instead.
  • Don't use setInterval() to update time or to update the UI (it's not reliable if you need ms precision). Always use requestAnimationFrame() to update the UI: this allows to update the UI immediately when there is a time change.
  • Remember to set Cache-Control: no-cache on the time returned by server.
  • For styling a digital clock using CSS, monospace fonts (like Roboto Mono) are perfect because when a digit changes, its width doesn't change (so the timer keeps a fixed width).

See it in action

On Time UTC you can see the algorithm in action and the source code.

Top comments (0)