The audit showed only 5 of ~11 time-display surfaces converted to the
user's timezone; everything else rendered pgx-decoded UTC. The server
owns conversion — clients (web/app/KOReader) receive display-ready
strings or machine-readable instants and never convert.
- Progress page: LastUpdated formatted in the requesting user's tz
(was raw UTC).
- Analytics: date-range defaults, day buckets, most-active-day, device
last-sync, and popular-book last-read all computed in the user's tz —
evening sessions no longer land on the next UTC day. Also fixed the
end-date boundary: the query bounds with <= and the end bound was
midnight, so the end date's own sessions (including 'today') never
appeared.
- Queue page: new created_at_display field (admin tz) rendered by the
template; created_at stays RFC3339 for API consumers.
- Admin hash-conflicts SSR bridge: detected date rendered in the
admin's tz.
- OPDS: .UTC() before the Z-suffixed feed timestamps (honesty fix —
correct today only because the session zone happens to be UTC).
- KOReader annotation datetimes deliberately untouched (device owns its
display).
Go's new() builtin takes a type and allocates a zero value — it cannot
wrap an expression. All instances of new(someExpression) were compile
errors. Replace each with a local variable assignment and address-of
operator.
Affected files:
- handlers/koreader.go: progress field pointers (Chapter, Page, etc.)
- handlers/kobo.go: pagesRemaining pointer
- handlers/queue.go: uuidPtrToString and timestamptzPtrToString helpers
- router/reader.go: bookmark pageNumber and chapterNumber pointers
- services/media_scanner.go: validation error message pointers
- services/worker.go: StartedAt and CompletedAt timestamps
- sync/offline.go: GetDeviceStatus return pointer
- tests/device_test.go: SyncEnabled and SyncFrequencyMinutes pointers
Simplify pointer creation across kobo, koreader, and queue handlers by
replacing the two-step pattern (assign to local, then take address) with
inline new() calls. This reduces verbosity without changing behavior:
Before:
remaining := int(a - b)
pagesRemaining = &remaining
After:
pagesRemaining = new(int(a - b))
Covers page calculations, chapter/progress fields, UUID formatting,
and timestamp string conversions.