diff options
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/superpowers/plans/2026-09-17-weather-widget.md | 25 |
1 files changed, 23 insertions, 2 deletions
diff --git a/docs/superpowers/plans/2026-09-17-weather-widget.md b/docs/superpowers/plans/2026-09-17-weather-widget.md index c19b253..0b78b83 100644 --- a/docs/superpowers/plans/2026-09-17-weather-widget.md +++ b/docs/superpowers/plans/2026-09-17-weather-widget.md @@ -643,6 +643,17 @@ assert(weather.age_str(1000, 1000 + 90) == '1m', 'ninety seconds reads as 1m') assert(weather.age_str(1000, 1000 + 3600) == '1h', 'an hour reads as 1h') assert(weather.age_str(1000, 1000 + 7200) == '2h', 'two hours') assert(weather.age_str(1000, 1000 + 86400 * 2) == '2d', 'days, once it gets that bad') + +-- Neither takes `now` on faith: a nil there used to raise, and a raise is a +-- blank dashboard rather than a message. +assert(weather.is_stale(1000, nil) == true, 'a nil now must not raise') +assert(weather.age_str(1000, nil) == '?', 'a nil now must not raise') + +-- A dt in the future means a clock skew. "stale -17m" reads as a broken +-- widget, so the age floors at zero and the reading counts as fresh. +assert(weather.age_str(2000, 1000) == '0m', 'a future dt reads as 0m, got ' .. + tostring(weather.age_str(2000, 1000))) +assert(weather.is_stale(2000, 1000) == false, 'a future dt is not stale') ``` - [ ] **Step 2: Run test to verify it fails** @@ -658,15 +669,25 @@ Add to `lib/weather.lua`, before the final `return M`: -- Three missed fetches at the 15-minute interval. M.STALE_AFTER = 45 * 60 +-- `now` is guarded alongside `dt` although every caller passes os.time(), +-- which cannot be nil: these were the only two functions in the module that +-- did arithmetic on an unchecked argument, and the module's promise is that +-- nothing raises. A raise here is a blank dashboard. function M.is_stale(dt, now) - if type(dt) ~= 'number' then return true end + if type(dt) ~= 'number' or type(now) ~= 'number' then return true end return (now - dt) > M.STALE_AFTER end -- Short age for the marker beside the city: "12m", "3h", "2d". +-- +-- A negative age is clamped to zero rather than printed. An observation +-- timestamped in the future means a clock skew somewhere, and "stale -17m" on +-- the card reads as a broken widget; treating it as fresh is both tidier and +-- truer, since weather from the future is not old. function M.age_str(dt, now) - if type(dt) ~= 'number' then return '?' end + if type(dt) ~= 'number' or type(now) ~= 'number' then return '?' end local s = now - dt + if s < 0 then s = 0 end if s < 3600 then return math.floor(s / 60) .. 'm' end if s < 86400 then return math.floor(s / 3600) .. 'h' end return math.floor(s / 86400) .. 'd' |
