Read the GA4 day on the property's clock, not on UTC - #3
Merged
Conversation
GA4 dates every row by the reporting timezone configured on the property, and this one is on UTC+3. The supplement worked out "today" with a UTC calendar, so for the three hours between 21:00 UTC and midnight the property had already started a day that UTC had not reached — the panel then showed the previous day's finished count as though it were today's movement, and dated the figures a day behind. West of UTC the error runs the other way and lasts longer: a Los Angeles property would spend every evening showing a day that is still filling in as if it were settled. The response already carries the answer. `metadata.timeZone` comes back with every runReport, so the client now hands it to the caller alongside the rows, and the supplement reads the current day on that clock. Row dates stay UTC-anchored labels, which is the one calendar the whole panel dates figures in; only the question of which label is today needed the property's zone. `endDate` is now GA4's own `today` keyword rather than a date computed here, for the same reason: a UTC-derived end date can cut the property's current day short. That also makes the end parameter meaningless to a caller, so it is gone from the protocol. A response with no readable timezone falls back to UTC rather than failing. The counts are still correct; only the today/not-today split degrades to the old behaviour. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EZ2Y7A3ZjdPCNSRzWDYVha
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The defect
GA4 dates every row by the reporting timezone configured on the property. This property is on
Etc/GMT-3— UTC+3 — which the live API confirms inmetadata.timeZone.GoogleAnalyticsInstallsService.supplementworked out "today" with a UTC calendar instead.Between 21:00 UTC and midnight the property has already begun a day UTC has not reached. GA4 files those events under tomorrow's label, the UTC-based filter does not match it, and the panel shows the previous day's finished count as though it were today's movement — while dating the figures a day behind.
West of UTC it is worse and lasts longer. A Los Angeles property spends every evening presenting a day that is still filling in as if it were settled.
The fix
metadata.timeZonealready comes back with everyrunReport, so nothing new is fetched. The client returns it alongside the rows and the supplement reads the current day on that clock.Row dates stay UTC-anchored labels — that is the one calendar the whole panel dates figures in (
PlayInstallsReport,Fmt.day). Only "which label is today" ever needed the property's zone.endDatebecomes GA4's owntodaykeyword rather than a date computed locally, since a UTC-derived end can cut the property's current day short. That leaves the end parameter meaningless to callers, so it is gone from the protocol:startDatestays UTC-formatted on purpose, and now says why in a comment: it is Play's newest report day plus one, and Play's report days are parsed as UTC labels.A response with no readable timezone falls back to UTC rather than throwing — the counts are still right, only the today/not-today split degrades to the old behaviour.
Verification
Both new tests were confirmed to fail against the previous logic before the fix landed:
make test— 144 tests, all passing (140 before, +4)swift build -c release— cleanendDate: "today"returns HTTP 200, andmetadata.timeZonereturnsEtc/GMT-3for this property.Not included
A README note about the property's reporting timezone. #2 already edits
README.md; a second independent edit across two open PRs buys a merge conflict and no behaviour. Worth adding once both land.🤖 Generated with Claude Code
https://claude.ai/code/session_01EZ2Y7A3ZjdPCNSRzWDYVha