# time.countdown How long is left until a moment, as a number and as the text a timer shows: ``` countdown(1790427600, 1790424000) # {expired: false, seconds: 3600, text: "1:00:00"} countdown(1000754, 1000000) # {expired: false, seconds: 754, text: "12:34"} countdown(1790427600, 1790427600) # {expired: true, seconds: 0, text: "0:00"} ``` Use it for an access token's remaining life (`until` is the token's `exp`), for how long a locked-out login must wait (`until` is now plus Retry-After), or for a cookie's `Max-Age` (`seconds`). The caller reads the clock and passes `now`, so the function stays pure and a page can call it once a second to tick. **Reached means expired.** The moment is reached at `until` itself, not one second later: RFC 7519 section 4.1.4 says a token MUST NOT be accepted "on or after" its `exp`. So `now == until` is `expired: true` with `seconds: 0`, and `expired` is exactly `seconds == 0`. A moment already past is also 0, never negative, so a timer never shows "-0:05". **Text.** `m:ss` under an hour (`0:59`, `12:34`), `h:mm:ss` from an hour up (`1:00:00`). Hours are not wrapped at 24, because a wait is a length of time and not a time of day: 25 hours and a bit is `25:01:01`. **Whole seconds.** Both arguments are whole Unix seconds, as JWT `exp` and `time.iso-to-unix` give them. A fraction (JavaScript's `Date.now() / 1000` not floored) is refused: "until must be a whole number of seconds" or "now must be a whole number of seconds".