"Days since I last smoked." "Days since the last production incident." "Days without sugar." A streak counter looks like the easiest widget in the world: store a start date and subtract. Then it shows 0 for two days after a clock change, crashes on the one user whose localStorage holds garbage, and stays on yesterday's number when the tab is left open overnight.
Here's the version I ended up with. It's plain JavaScript plus one React hook, with no libraries. All the logic below was run under Node 20 with TZ=Europe/Warsaw and TZ=America/New_York .
Rule 1: store calendar days, not timestamps
A streak is about days the user lived through , not milliseconds. If you store Date.now() and divide by 86,400,000, a 23-hour DST day or a trip across time zones will shift your count. So store a local day key , a plain YYYY-MM-DD string:
export function toDayKey ( date = new Date ()) { const y = date . getFullYear (); const m = String ( date . getMonth () + 1 ). padStart ( 2 , " 0 " ); const d = String ( date .…