Count Down to a Future Date in JavaScript
To count down to a future moment, subtract now from the target as a Temporal.Duration and balance it into days/hours/minutes/seconds with round. Part of Temporal.Duration Arithmetic.
Why this scenario is tricky
Naive countdowns compute targetMs - Date.now() and then do modular arithmetic by hand, which drifts and mishandles the final tick. Temporal gives you the signed gap as a Duration and balances it into whole units, so the display reaches exactly 0d 0h 0m 0s at the target.
Minimal working solution
import { Temporal } from '@js-temporal/polyfill';
const target = Temporal.Instant.from('2026-12-31T23:59:59Z');
const d = target.since(Temporal.Now.instant(), { largestUnit: 'day' });
// d.days, d.hours, d.minutes, d.seconds
Full production version
import { Temporal } from '@js-temporal/polyfill';
function remaining(target: Temporal.Instant) {
const diff = target.since(Temporal.Now.instant(), { largestUnit: 'day', smallestUnit: 'second' });
return Temporal.Duration.compare(diff, {}) <= 0
? { days: 0, hours: 0, minutes: 0, seconds: 0 } // clamp once elapsed
: diff;
}
Verification snippet
Common pitfalls
Frequently Asked Questions
How do I build a countdown timer in JavaScript?
Compute target.since(Temporal.Now.instant(), { largestUnit: 'day' }) on each tick to get the remaining time as a balanced Temporal.Duration, then display its days, hours, minutes, and seconds. Re-evaluate on an interval and clamp to zero once the target passes.
Why does my countdown skip or repeat the last second?
Hand-rolled modulo on a millisecond gap accumulates rounding error and mishandles the boundary at zero. Using Temporal.since with a smallestUnit of 'second' balances the remaining time into whole units so it lands exactly on zero.