“Today’s steps” is the most bug-prone number in a fitness app
It looks trivial and it is not. A civil day is only usually 24 hours long, so any daily total computed over a fixed UTC window is quietly wrong on the two days a year a timezone shifts. Pick a zone and a daylight-saving day below and watch it happen — every number computed live in your browser from its own timezone database.
- Local day starts
- 8 Mar 2026, 00:00
- = 8 Mar 2026, 08:00 UTC
- Local day ends
- 9 Mar 2026, 00:00
- = 9 Mar 2026, 07:00 UTC
- UTC offset that day
- UTC−08:00 → UTC−07:00
- Length of this civil day
- 23 hours(not 24 — DST spring forward)
This civil day is 23 hours long, not 24. If your daily total queries a fixed [midnight, midnight+24h) UTC range, you just droppedan hour of this user’s data — the classic bug that makes step counts and streaks wrong twice a year. Store the local civil date, not just the instant.
Computed live in your browser from its own IANA timezone database — nothing here is a number we hardcoded.
Why this bites health apps specifically
In most software a mislabelled day is cosmetic. In a fitness app it corrupts the numbers users check obsessively: a step count that drops an hour reads as the app losing their walk, a streak that spans a DST night breaks when it shouldn’t, and a “daily average” computed over 23- and 25-hour days is subtly off forever. The user knows how far they walked; when your number disagrees, they trust the app less.
The full storage model — instant plus offset plus civil date, and how to recompute a day that a late-arriving sample makes stale — is in timezones and day boundaries. The broader “samples are late-arriving, not append-only” problem this is part of lives in incremental sync, and the test-data guide explains why a DST night belongs in your fixtures.
Frequently asked questions
- Why isn't a day always 24 hours?
- Because of daylight-saving transitions. On the day a zone springs forward, the clock skips an hour, so the civil day is 23 hours long; on the day it falls back, an hour repeats and the day is 25 hours. A daily total that assumes every day is a fixed 24-hour UTC window will include or drop an hour of a user's activity on exactly those two days a year, and the bug is invisible the rest of the time.
- How should I store a daily total so this doesn't happen?
- Store the instant (UTC) for each sample, the UTC offset in effect at that instant, and — where your product needs a per-day figure — the local civil date the sample belongs to. Compute 'today' against the user's local midnight, resolved through a real timezone database, not against a fixed UTC range. UTC alone loses the information you need to answer 'which day was this'; local time alone loses the ability to order events. You need both.
- Does this demo use data you collected about timezones?
- No. Everything on this page is computed in your browser from the platform's own IANA timezone database via the built-in Intl API. There are no timezone facts we hardcoded, so nothing here can be stale or wrong about a specific zone — your device is the source.
A free interactive demo from AIFitnessAPI. Independent and not sponsored — link it if it helps you explain this to someone.