How remaining time is computed
When you create a timer, the date, time, and time zone you pick are converted to a UTC ISO 8601 timestamp once, at save time. From then on the remaining time is pure arithmetic, implemented bygetCountdownParts in lib/utils.ts:
Where “now” comes from
The current time is sampled by theuseNow hook in components/use-now.ts:
it reads Date.now() and re-samples it once per second with setInterval.
Two practical consequences:
- No drift. Because each tick recomputes
target - nowfrom absolute timestamps, a delayed tick cannot accumulate error. If the browser throttles timers in a background tab or the laptop sleeps, the display may pause, but the very next tick is exactly right again. - It trusts the device clock.
Date.now()is the device’s wall clock. If the device clock is two minutes off, the displayed remaining time is two minutes off as well. There is no server time synchronization.
Time zones and recurrence
Converting your wall-clock input (“June 30 at 09:00 in Europe/Warsaw”) to UTC uses thedate-fns-tz library, which delegates to the browser’s built-in
Intl.DateTimeFormat and its IANA time zone database. Daylight saving rules
come from the browser, so they stay current with browser updates.
Recurring timers store a wall-clock pattern in the timer’s time zone and
compute the next occurrence on demand. Occurrences are calculated, never
mutated, so the countdown is correct even if the app was closed while several
occurrences passed.
Browser support
| API | Used for | Support |
|---|---|---|
Date.now() | sampling the current time | every browser since ES5 |
setInterval | the 1-second tick | universal |
Intl.DateTimeFormat with IANA timeZone | time zone conversion | all evergreen browsers |
Intl.DateTimeFormat time
zone handling in long-obsolete browsers.
To verify support yourself:
- caniuse.com - search the feature, for example
Internationalization API for
Intl.DateTimeFormator Date.now. - MDN - every API page ends with a browser compatibility table, for example Intl.DateTimeFormat.