fix(admin): parse SQLite timestamps as UTC#1121
Open
eyupcanakman wants to merge 1 commit into
Open
Conversation
SQLite datetime('now') stores timestamps with no timezone suffix, which new Date() reads as local time.
Revision and dashboard timestamps in the admin UI drifted by the viewer's offset.
Closes emdash-cms#919
🦋 Changeset detectedLatest commit: 4a27b66 The changes in this PR will be included in the next version bump. This PR includes changesets to release 13 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
@emdash-cms/admin
@emdash-cms/auth
@emdash-cms/blocks
@emdash-cms/cloudflare
emdash
create-emdash
@emdash-cms/gutenberg-to-portable-text
@emdash-cms/x402
@emdash-cms/plugin-ai-moderation
@emdash-cms/plugin-atproto
@emdash-cms/plugin-audit-log
@emdash-cms/plugin-color
@emdash-cms/plugin-embeds
@emdash-cms/plugin-forms
@emdash-cms/plugin-webhook-notifier
commit: |
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes incorrect admin-side timestamp rendering for SQLite-backed sites by ensuring “naive” DB timestamps (no timezone suffix) are interpreted as UTC in the admin UI, and by adjusting browser test execution to catch local-vs-UTC parsing differences.
Changes:
- Add
parseTimestamp()utility that treats timestamps withoutZ/offset as UTC and route relative/full-date formatting through it. - Update revision history and dashboard relative-time formatting to use the normalized timestamp parser.
- Pin Vitest browser timezone to a non-UTC zone and add unit tests covering SQLite,
Z, offsets, and Postgres-style offsets.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| packages/admin/vitest.config.ts | Pins Playwright browser context timezone to ensure timestamp parsing bugs are caught in CI. |
| packages/admin/tests/lib/utils.test.ts | Adds parseTimestamp test coverage for naive SQLite timestamps and zoned variants. |
| packages/admin/src/lib/utils.ts | Introduces parseTimestamp and updates formatRelativeTime to use it. |
| packages/admin/src/components/RevisionHistory.tsx | Uses parseTimestamp for full timestamp display in revision history UI. |
| .changeset/fix-revision-date-utc.md | Adds a patch changeset describing the admin timestamp fix. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+29
to
+33
| const hasZone = TIMEZONE_DESIGNATOR_PATTERN.test(value); | ||
| if (hasTime && !hasZone) { | ||
| return new Date(value.replace(" ", "T") + "Z"); | ||
| } | ||
| return new Date(value); |
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.
What does this PR do?
Admin revision timestamps showed the wrong relative and absolute date on SQLite-backed sites.
datetime('now')stores values asYYYY-MM-DD HH:MM:SSwith no timezone suffix, andnew Date()parses that form as local time, so a revision created seconds ago rendered as hours ago for any viewer not on UTC.parseTimestampinpackages/admin/src/lib/utils.tsnow treats a timestamp with noZor numeric offset as UTC, matching thereplace(" ", "T") + "Z"form already used in the WXR importer.formatRelativeTimeand the revision panel'sformatFullDateboth parse through it. Values that already carry a timezone are returned unchanged.The admin browser tests run on a UTC CI runner, where parsing as local time gives the same result as UTC, so the bug would slip through. The vitest config now pins a non-UTC
timezoneIdso theparseTimestamptests exercise the offset path.Closes #919
Type of change
Checklist
pnpm typecheckpassespnpm lintpassespnpm testpasses (or targeted tests for my change)pnpm formathas been runmessages.pochanges except in translation PRs — a workflow extracts catalogs on merge tomain.AI-generated code disclosure
Screenshots / test output