A monthly utility billing run double-charged accounts on the night clocks shifted back. How would you test its timezone and calendar handling?
answer
- Make time an input, not ambient
- Three concepts kept apart
- One local hour occurs twice
- Key the ledger by calendar period
- Per-account uniqueness, never the total
basics
~10 sDrive the run from an injected clock, not the machine clock, and enumerate boundary dates deliberately: the repeated local hour, the missing one, month ends, fractional offsets. Assert one charge per account per period.
solid answer
~50 sThe root cause of this family is collapsing three concepts: an absolute instant, a local wall-clock reading, and a calendar billing period. Keying a charge by the run's local start time means the repeated local hour produces a second pass that the ledger check does not recognise as a repeat. Test it by making time an input: inject the clock so any date is reachable in seconds, then run the boundary catalogue — clocks shifting back and forward, month ends of 28, 29, 30 and 31 days, the year boundary, a region with a fractional offset, a region that changed its rules, a region with no seasonal shift mixed into the same run, and an account whose declared region differs from the server's. The oracle is a per-account uniqueness assertion, not the run total; rerun the job and assert the second pass writes nothing.
code
pseudocode · 8 lines// period is a calendar interval in the account's declared region
period = billingPeriodFor(clock.instant(), account.region) // e.g. "2026-08"
key = account.id + ":" + period
if ledger.hasCharge(key):
skip(account) // a rerun writes nothing
else:
ledger.charge(key, amountFor(account, period))go deeper
Know that a local time is not the same thing as an absolute instant, and that on one night a year a local hour repeats. Being able to say why storing wall-clock text is risky is enough at this level.
Explain the mechanics: instants versus local readings versus calendar periods, why period arithmetic belongs in the account's declared region, and why a job needs an injected clock before any of this becomes testable.
Demonstrate the diagnosis and the boundary catalogue: reproduce with a fixed clock, assert per-account uniqueness, prove rerun-safety by running twice, and seed regions with fractional offsets and changed rules into the dataset.
Own the invariant across services: one storage convention for instants, calendar periods as the ledger key, idempotent jobs by policy so a scheduling surprise is a no-op, and a standing boundary suite that runs on every build rather than once a year.
### The three time concepts that must stay separate Almost every recurring-job time defect comes from collapsing three distinct things into one field: 1. **An absolute instant** — a fixed point on the timeline, the same moment everywhere. This is what an event "happened at". 2. **A local wall-clock date-and-time** — what a clock on the wall in a given region reads. It is a *rendering* of an instant through a region's rules, and it is ambiguous: when clocks shift back, one local hour occurs twice; when they shift forward, one local hour does not occur at all. 3. **A calendar period** — "the August billing period for this account". This is neither an instant nor a wall-clock reading; it is a labelled interval whose boundaries are defined by a calendar and a region. The correct model for a billing run is: store instants absolutely with their offset context, do all period arithmetic in the account's *declared* region using calendar dates, and key each charge by the calendar period. Then re-running is a no-op rather than a second charge. ### How the duplicate happened The failure to reason about out loud is this one. The run was scheduled at a fixed local hour, chosen because the window had to fit the per-account processing budget — the team had sized it so the 92nd percentile of per-account processing finished inside the window. Period boundaries were derived by subtracting a fixed number of hours from the local start time, and the ledger key was the run's local start timestamp rather than the calendar period. On the night clocks shifted back, the scheduler's local hour occurred twice; the second pass computed a start timestamp identical to the first, produced a different period boundary for accounts whose local date had already rolled, and the ledger check compared against a key that no longer matched. 3,140 of 41,200 accounts were charged twice, and the run total was only 7.6% high, which is why nobody noticed until customers did. ### Designing the test **Control the clock.** The single most important structural move is that the run must take its time from an injected clock, not from the machine. A test that cannot set "now" can only test the day it runs. With an injectable clock, the whole boundary catalogue becomes ordinary automated tests that run in seconds on every build. **Enumerate the boundary catalogue** rather than sampling dates: - the local hour that occurs twice when clocks shift back, and the local hour that never occurs when they shift forward — run the job at, before and inside each; - month ends of 28, 29, 30 and 31 days, and the year boundary; - a region whose offset is not a whole number of hours; - a region that changed its rules between the stored data and the run; - a region that observes no seasonal shift at all, mixed into the same run as regions that do; - an account whose declared region differs from the region the server runs in, and from the region the operator is viewing from; - a display calendar that is not the one the code does arithmetic in, so period labels are rendered correctly without the arithmetic following the display. **Assert per account, not in aggregate.** The oracle that catches this class is "exactly one charge per account per billing period, and the period label matches the account's region" — expressed as a uniqueness assertion over the ledger. A total-revenue assertion passes happily while one account is charged twice and another is missed, and a run that is 7.6% high sits comfortably inside normal seasonal variation. **Test the idempotency directly.** Run the job twice over the same period with the clock moved forward by an hour, and assert the second pass writes nothing. Then kill the job mid-run and restart it, and assert the same. Rerun-safety is a property of the keying, and it is the property that turns a scheduling surprise from an incident into a no-op. **Test the reverse direction too.** A missing local hour is the mirror defect: a job keyed to a local time that does not exist that night silently skips a period, and the symptom arrives a month later as an under-bill. ### What to look for in the code while testing Ask where local wall-clock values are stored, where date arithmetic is done on local dates rather than on instants, whether "one month later" is defined by the calendar or by a fixed hour count, whether the region used is the account's declared region or an ambient default inherited from the process, and whether the ledger key can ever be produced twice for one period. Each of those questions maps directly to a test in the catalogue above. ### Reporting it A defect report here needs the account's declared region, the exact local and absolute times of both charges, the period key each pass computed, and the reproduction as a clock setting rather than as "wait until autumn". Without the clock injection, the report is unreproducible for six months, which is the real reason this class survives so long in production systems.
- Why does a run-total assertion fail to catch this defect?Because it aggregates away the per-account facts. A run where 3,140 of 41,200 accounts are charged twice moved the total by well under ten percent, which sits inside ordinary seasonal variation, and a total assertion also passes when one account is double-charged and another is missed. The assertion that catches it is uniqueness of account plus billing period over the ledger.
- What is the mirror-image defect when clocks shift forward instead of back?A job keyed to a local time that does not exist that night silently skips its run, or computes a period boundary an hour short, so a period is never billed. The symptom is an under-bill discovered a month later rather than an immediate complaint, which makes it harder to trace. The same injected-clock boundary catalogue covers it, with an assertion that every account has exactly one charge rather than at most one.
- Which regions would you deliberately seed into the test dataset?One with a fractional offset from the reference, one that observes no seasonal shift, one that shifts on a different date from the operator's region, one whose rules changed between the stored history and the run, and one where the account's declared region differs from both the server's and the operator's. Each of those has produced its own production incident class.
- How do you make this reproducible for whoever picks up the defect report?Report it as a clock setting, not as a season. Give the account's declared region, both charges with their absolute instants and their local readings, and the period key each pass computed. Attach the failing boundary case from the automated catalogue so the reader can reproduce it in seconds instead of waiting six months for the next shift.
A wall-clock reading is a description of a moment, not the moment itself. Two different descriptions can name the same instant, and on one night a year the same description names two.
saying these in an interview costs you the question
- Tests only with the machine's own clock
- Stores wall-clock text and compares strings
- Asserts the run total instead of per account
- Assumes every region shifts on the same date
- Believes all offsets are whole hours
- Treats reruns as inherently unsafe rather than fixing keying