Agree what the day means
Write the business reporting zone and which instant is counted: creation, payment or fulfilment. Those choices are business policy, not something to infer from a column name. Keep an invented record's offset-aware timestamp and its expected local day beside the actual report assignment.
- Record USE_TZ, the default zone and any per-user active zone.
- Compare raw timestamp, displayed timestamp and report filter separately.
- Do not use real order histories to establish the initial reproduction.
Convert the instant before taking its date
Django's guide explains that a datetime's date depends on its representation's zone. Extracting .date() from UTC is not automatically the business's local date. Construct the intended local day boundaries as aware instants and compare on a stated interval, such as start included and next start excluded. Do not assume every local day is exactly 24 hours.
- Avoid comparing naive and aware datetimes.
- Treat ambiguous imported local timestamps as exceptions needing an explicit policy, not an automatic guess.
- Keep interchange timestamps offset-aware or explicitly UTC.
Test the boundary, not just midday
An authored fixture places invented events immediately before, at and after the local-day boundary, plus the next day's start. Include the relevant DST transition for the chosen zone. Assert each included record ID and total; a plausible aggregate can hide one missing and one extra row. This is a test proposal, not a corrected financial report.
- Check the export and visible report apply the same agreed zone.
- Record filter instants and fixture IDs for independent inspection.
Non-fit and priced route
A deterministic wrong-day filter with synthetic timestamps may fit fix-one-bug-with-regression-test, from £295 after bounded reproduction and a fixed quote. Deciding accounting policy, reconciling real accounts or converting historical naive timestamps is not included: the finance owner sets policy and a separate authorised recovery plan handles history. A new report can be discussed under ship-one-feature-with-running-preview, from £750 after agreeing one feature and a private preview.
- No tax, accounting assurance or correction of posted transactions is offered by this guide.
- Initial inputs are the agreed reporting zone and invented expected/actual timestamps, never customer exports or access keys.
Sources and limits
- Django 5.2 time-zone support; BSD-licensed project documentation Checked 2026-10-11.
- With time-zone support Django uses aware datetimes and UTC internally.
- The same instant can have different dates in different zones.
- DST transitions create ambiguous or nonexistent local times.
- Naive datetime compatibility can warn and interpret values in the default zone.
- Current single-bug scope Checked 2026-10-11.