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:
- fetches authoritative time from your server (not
Date.now()
) - uses
performance.now()
to track elapsed time with a monotonic clock - renders instantly and smoothly via
requestAnimationFrame()
(nosetInterval()
) - compensates for network latency
- handles the real‑world details that make the difference between “pretty good” and “rock solid”.
The algorithm
- Sync: Fetch the server’s current UTC.
- Adjust for latency: Estimate one way latency (≈ RTT/2).
-
Save a local baseline: Record
start = performance.now()
at the moment the response arrives. - Simulate time: At any later instant, compute
estimated_time = server_utc_at_response + one_way_latency + (performance.now() - start)
-
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 ofDate.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 aPerformanceObserver
instead. - Don't use
setInterval()
to update time or to update the UI (it's not reliable if you need ms precision). Always userequestAnimationFrame()
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)