Skip to content

fix(data-table): serialize datetime filters as RFC 3339 - #546

Open
IzumiSy wants to merge 11 commits into
mainfrom
fix/datetime-filter-rfc3339
Open

IzumiSy wants to merge 11 commits into
mainfrom
fix/datetime-filter-rfc3339

Conversation

@IzumiSy

@IzumiSy IzumiSy commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Motivation

DataTable.Filters emitted local datetime strings without a timezone and passed them straight to GraphQL collection queries. Platform DateTime filters require RFC 3339 instants, so these values were not a reliable query contract.

Design Decision

Local-time selection, instant serialization

The picker continues to present the user's local date and time. On input it converts that local selection to an RFC 3339 UTC instant with Date#toISOString() rather than appending Z, which would change the selected instant. Existing instants are converted back to local picker parts when displayed.

Backward compatibility

Previously stored timezone-less datetime filters remain readable and are normalized when re-applied. Date and time filters retain their existing YYYY-MM-DD and HH:mm formats.

Summary

  • Serialize DataTable datetime filter values and ranges as RFC 3339 instants.
  • Render persisted datetime instants in the user's local timezone.
  • Document the filter contract and add regression coverage.

@github-actions

github-actions Bot commented Sep 17, 2026 •

Copy link
Copy Markdown
Contributor

Code Metrics Report

main (94f6a5a) #546 (28c783b) +/-
Coverage 88.1% 88.4% +0.2%
Test Execution Time 2m20s 2m19s -1s
Details
  |                     | main (94f6a5a) | #546 (28c783b) |  +/-  |
  |---------------------|----------------|----------------|-------|
+ | Coverage            |          88.1% |          88.4% | +0.2% |
  |   Files             |            207 |            207 |     0 |
  |   Lines             |           6176 |           6225 |   +49 |
+ |   Covered           |           5446 |           5507 |   +61 |
+ | Test Execution Time |          2m20s |          2m19s |   -1s |

Code coverage of files in pull request scope (79.7% → 83.0%, patch 82.3%)

Files Coverage +/- Patch Coverage Status
packages/core/src/components/data-table/filter-value-utils.ts 90.7% -4.9% 86.6% modified
packages/core/src/components/data-table/toolbar.tsx 82.3% +3.7% 81.4% modified

Reported by octocov

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Datetime handling remains inconsistent across configured timezones and operator changes, while permissive parsing can silently alter invalid values.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Updates DataTable datetime filters to use RFC 3339 instants while retaining local-time editing.

Changes:

  • Normalizes datetime values during editing and submission.
  • Displays persisted instants as local picker values.
  • Adds documentation, tests, and release metadata.
File summaries
File Description
packages/core/src/components/data-table/toolbar.tsx Applies datetime conversion in filter editors.
packages/core/src/components/data-table/toolbar.test.tsx Tests datetime serialization and ranges.
packages/core/src/components/data-table/filter-value-utils.ts Adds normalization and local-part helpers.
packages/core/src/components/data-table/filter-value-utils.test.ts Tests normalization and picker hydration.
docs/components/data-table.md Documents the RFC 3339 contract.
.changeset/bright-clocks-wait.md Records the patch-level behavior fix.
Review details
  • Files reviewed: 6/6 changed files
  • Comments generated: 3
  • Review effort level: Balanced

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread packages/core/src/components/data-table/filter-value-utils.ts
Comment thread packages/core/src/components/data-table/filter-value-utils.ts Outdated
Comment thread packages/core/src/components/data-table/toolbar.tsx Outdated
IzumiSy and others added 5 commits September 29, 2026 12:37
Co-authored-by: IzumiSy <982850+IzumiSy@users.noreply.github.com>
Co-authored-by: IzumiSy <982850+IzumiSy@users.noreply.github.com>
Co-authored-by: IzumiSy <982850+IzumiSy@users.noreply.github.com>
Co-authored-by: IzumiSy <982850+IzumiSy@users.noreply.github.com>
@IzumiSy
IzumiSy force-pushed the fix/datetime-filter-rfc3339 branch from e2ee407 to fb64592 Compare September 29, 2026 03:37
@IzumiSy

IzumiSy commented Oct 6, 2026

Copy link
Copy Markdown
Contributor Author

@copilot fix CI errors

Co-authored-by: IzumiSy <982850+IzumiSy@users.noreply.github.com>

Copilot AI commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

@copilot fix CI errors

Addressed in 78003cc. I fixed the remaining datetime validation paths to use the configured AppShell timezone consistently and verified with targeted DataTable tests plus lint.

@IzumiSy
IzumiSy marked this pull request as ready for review October 6, 2026 06:29
@IzumiSy
IzumiSy requested a review from a team as a code owner October 6, 2026 06:30
@IzumiSy

IzumiSy commented Oct 6, 2026

Copy link
Copy Markdown
Contributor Author

@copilot fix CI errors by fixing docs

Co-authored-by: IzumiSy <982850+IzumiSy@users.noreply.github.com>

Copilot AI commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

@copilot fix CI errors by fixing docs

Fixed in 514914f. I resynced the generated DataTable docs outputs with the docs pipeline and verified pnpm docs:check passes locally.

@interacsean interacsean left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll need to be loud about the importance of

If it is not specified as the business's timezone, then filtering may have unexpected results — For us in Australia/Japan timezones, when we search for a date, we may get misses when we expect hits for document dates that are coded on a US timezone

The real problem here is that document dates which are calendar dates, are coded as instants, which is incorrect but this was a problem we created some time ago

@interacsean

interacsean commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Claude found:

Major
Saved and starting filters still reach GraphQL without a timezone.
use-collection-variables.ts:227, collection-url-state.ts:112
The query builder sends filter.value exactly as it is stored. Normalization only happens inside the toolbar editors, on Apply, Update or an operator switch.
So these all still send an old zone-less value like 2026-10-09T00:00:00 to GraphQL until someone opens and re-applies the chip:

  • a bookmarked or shared URL
  • an initialFilters value set in code
  • a saved view

The description admits this (“normalized when re-applied”), but it undercuts the stated reason for the PR, which is a reliable query contract.

Fix: normalize where values enter the system. parseCollectionSearchParams already has the table metadata and knows the field types, so it can normalize datetime fields there. The DataTable could also normalize its filters once when it mounts.

The timezone isn’t used everywhere, so filters and cells can disagree.
cell-renderers.tsx:131, data-table.tsx:165
Filters and chip labels now use the AppShell timeZone, but:

  • date cells still format with Intl.DateTimeFormat and no timeZone, so they show the browser’s zone;
  • the cell menu’s “Filter by this value” calls normalizeTemporalFilterValue without a zone, so a zone-less cell value is read in the browser’s zone.

When the two zones differ (the exact setup the new tests use), a row can display as 9 Oct 01:00 while a filter for “after 9 Oct 00:00” excludes it.

Fix: pass useTimeZone().value into the date cell renderer and into toFilterValue.

A visible contract change ships as a patch, and the docs weren’t updated.
bright-clocks-wait.md, data-table.docs.outline.md:706
The description says the filter contract is documented, but the final diff has no prose change. The doc edit was made under docs/, which is generated, and the later resync overwrote it. The outline still describes datetime as “Datetime-local”.
Two behaviour changes go undocumented:

  • Any consumer reading collection.filters or the addFilter payload now gets …Z strings instead of local ones.
  • For apps that don’t set timeZone, results now depend on where each user is (the purchase-order case from earlier). Before, everyone effectively searched the same way.

Fix:

  • Add the instant contract to the docs-src outline.
  • Tell apps to set timeZone for business-day semantics.
  • Point date-only fields (like a purchase-order date) at the date type.
  • Call out the consumer-visible change in the changeset, and consider a minor bump instead of a patch.

@IzumiSy

IzumiSy commented Oct 9, 2026

Copy link
Copy Markdown
Contributor Author

@copilot resolve the merge conflicts in this pull request

…fc3339

# Conflicts:
#	docs-manifest.json

Co-authored-by: IzumiSy <982850+IzumiSy@users.noreply.github.com>

Copilot AI commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

@copilot resolve the merge conflicts in this pull request

Resolved in 33e3fed. I merged the latest main into this branch, resolved the manifest conflict by regenerating the docs artifacts, and verified the docs check passes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants