fix(db): parse timestamp columns as UTC regardless of server timezone#223
Merged
Conversation
All `timestamp without time zone` columns store UTC by convention, but node-pg's default parser interprets them in the server's local timezone. Every sync path assumes UTC via toISOString()/getTime() — QRZ/LoTW ADIF date/time emission, both +/-15-minute confirmation matchers, and the .tq8 signer — so a self-hosted install with TZ != UTC shipped skewed QSO times and mismatched confirmations. On Vercel (TZ=UTC) this is a no-op. Register a pg type parser for OID 1114 in getPool() that reads timestamps back as UTC, and document the convention in drizzle/schema.ts. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
There was a problem hiding this comment.
Pull request overview
This PR addresses a timezone-related correctness issue in Nextlog’s PostgreSQL access layer by ensuring timestamp without time zone values (stored as UTC by convention) are parsed back into JavaScript Date objects as UTC, regardless of the host server’s local timezone. This prevents silent time skew that breaks downstream sync/export logic (QRZ/LoTW/ADIF matching, signing, etc.) on self-hosted deployments with TZ≠UTC.
Changes:
- Register a node-postgres type parser for OID
1114(timestamp without time zone) ingetPool()to interpret returned timestamps as UTC. - Document the project-wide UTC storage convention for
timestampcolumns in the Drizzle schema.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/lib/db.ts | Adds a pg type parser override so timestamp without time zone is parsed as UTC instead of local time. |
| drizzle/schema.ts | Documents the UTC-by-convention rule for timestamp columns and references the db parser behavior. |
node-pg's default Date serialization emits local-time strings, and timestamp-without-time-zone columns ignore the trailing offset, so on a non-UTC Node process Dates written by Contact.ts / adif.ts would be stored as local wall-clock and then misread as UTC by the new parser. pg.defaults.parseInputDatesAsUTC = true makes Date params serialize as UTC (+00:00), which is also lossless for timestamptz columns. Addresses Copilot review feedback on #223. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
Problem
contacts.datetime(and every other timestamp column) istimestamp without time zone, storing UTC by convention. node-pg's default parser interprets those values in the server's local timezone — but every sync path assumes UTC viatoISOString()/getTime(): QRZ/LoTW ADIF date/time emission, both ±15-minute confirmation matchers, and the.tq8signer. On Vercel (TZ=UTC) everything lines up; on a self-hosted box with TZ≠UTC, QSO times ship skewed by the UTC offset and confirmations stop matching.Fix
Register a pg type parser for OID 1114 (
timestamp without time zone) ingetPool()that reads timestamps back as UTC (new Date(value.replace(' ', 'T') + 'Z')), and document the UTC convention at the top ofdrizzle/schema.ts. No behavior change on Vercel; correctness fix for self-hosted.Verification
npm run lint/npm run typecheck/npm run buildclean.TZ=America/New_York, read a contact and checkdatetime.toISOString()matches the stored literal value.🤖 Generated with Claude Code