Skip to content

feat(analytics): datetime date-bucket drill uses reference-tz midnight instants (#1752 follow-up)#3272

Merged
os-zhuang merged 1 commit into
mainfrom
claude/report-drill-down-range-filter-lxt859
Jul 19, 2026
Merged

feat(analytics): datetime date-bucket drill uses reference-tz midnight instants (#1752 follow-up)#3272
os-zhuang merged 1 commit into
mainfrom
claude/report-drill-down-range-filter-lxt859

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Why

Follow-up to #3256 (which landed #1752). That change deliberately left one gap: a datetime date dimension bucketed under a non-UTC reference timezone fell back to a superset drill. A datetime bucket's boundary is that timezone's midnight instant, which the YYYY-MM-DD calendar bounds couldn't express — so rather than emit a wrong (tz-offset) bound, it emitted none. This closes that gap.

What

  • @objectstack/core — add zonedDateStartToUtcMs(ymd, tz): the UTC instant at which calendar day ymd begins in reference timezone tz (the inverse of calendarPartsInTz). DST-safe — the offset is read from the platform tz database via Intl.DateTimeFormat, with a two-pass resolution for the rare offset-boundary case; an unset / 'UTC' / invalid zone returns plain UTC midnight.
  • @objectstack/service-analytics — emit drillRanges bounds per the field's temporal type (ADR-0053):
    • datetime → ISO instant bounds at the reference tz's midnight (works under any tz, including DST);
    • dateYYYY-MM-DD calendar bounds (tz-naive, exact under any tz);
    • unknown field type → still emitted only under UTC, omitted (superset) under a non-UTC tz.

No objectui change — the client already forwards whatever bound values the server sends into the drill filter and the filter[field][gte|lt] URL contract, so ISO-instant bounds flow through unchanged.

Testing

  • zonedDateStartToUtcMs (9 cases): fixed offset (Asia/Shanghai +08), DST zone summer/winter (America/New_York EDT/EST), DST-transition days, unknown zone → UTC, unparseable → NaN, plus a round-trip that proves the instant lands exactly on the day boundary in the zone.
  • Analytics emission: a datetime dim under America/New_York now drills 2026-06-01T04:00:00.000Z → 2026-07-01T04:00:00.000Z (EDT midnight = 04:00 UTC).
  • Green: @objectstack/service-analytics 170/170, @objectstack/objectql date-bucket-range 49/49 (regression), core datetime 9/9; type-check clean (DTS build).

🤖 Generated with Claude Code

https://claude.ai/code/session_01RCXBnmMQTwjmFkjtpEe11f


Generated by Claude Code

…t instants (#1752 follow-up)

A `datetime` date dimension bucketed under a non-UTC reference tz previously fell
back to a superset drill (its bucket boundary is that tz's midnight instant, which
YYYY-MM-DD calendar bounds can't express). Emit those instants instead, closing the
last gap from the initial #1752 change.

- core: add `zonedDateStartToUtcMs(ymd, tz)` — the UTC instant a calendar day
  begins in a reference tz (inverse of calendarPartsInTz). DST-safe via Intl with a
  two-pass offset resolution; unset/UTC/invalid zone → plain UTC midnight.
- service-analytics: emit drillRanges bounds by field temporal type (ADR-0053) —
  datetime → ISO instant at the tz's midnight (any tz, incl. DST); date →
  YYYY-MM-DD calendar (tz-naive). Unknown type stays UTC-only.

objectui needs no change — the client already forwards arbitrary bound values into
the drill filter and the filter[field][gte|lt] URL.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RCXBnmMQTwjmFkjtpEe11f
@vercel

vercel Bot commented Jul 19, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
spec Ready Ready Preview, Comment Jul 19, 2026 12:02pm

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling labels Jul 19, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/core, packages/services.

26 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/actions-as-tools.mdx (via @objectstack/core)
  • content/docs/ai/knowledge-rag.mdx (via @objectstack/core)
  • content/docs/ai/natural-language-queries.mdx (via @objectstack/core)
  • content/docs/automation/webhooks.mdx (via @objectstack/core, packages/services)
  • content/docs/concepts/north-star.mdx (via packages/core)
  • content/docs/deployment/migration-from-objectql.mdx (via @objectstack/core)
  • content/docs/kernel/contracts/index.mdx (via @objectstack/core)
  • content/docs/kernel/runtime-services/audit-service.mdx (via packages/services)
  • content/docs/kernel/runtime-services/examples.mdx (via @objectstack/core)
  • content/docs/kernel/runtime-services/index.mdx (via packages/services)
  • content/docs/kernel/runtime-services/settings-service.mdx (via packages/services)
  • content/docs/kernel/services-checklist.mdx (via @objectstack/core)
  • content/docs/kernel/services.mdx (via @objectstack/core)
  • content/docs/permissions/authentication.mdx (via @objectstack/core)
  • content/docs/permissions/authorization.mdx (via packages/core)
  • content/docs/plugins/anatomy.mdx (via @objectstack/core)
  • content/docs/plugins/development.mdx (via @objectstack/core)
  • content/docs/plugins/index.mdx (via @objectstack/core)
  • content/docs/plugins/packages.mdx (via @objectstack/core, packages/services)
  • content/docs/protocol/kernel/config-resolution.mdx (via @objectstack/core)
  • content/docs/protocol/kernel/i18n-standard.mdx (via packages/services)
  • content/docs/protocol/kernel/index.mdx (via @objectstack/core)
  • content/docs/protocol/kernel/lifecycle.mdx (via @objectstack/core)
  • content/docs/protocol/kernel/plugin-spec.mdx (via @objectstack/core)
  • content/docs/releases/implementation-status.mdx (via @objectstack/core)
  • content/docs/releases/v15.mdx (via @objectstack/core)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@os-zhuang
os-zhuang marked this pull request as ready for review July 19, 2026 12:10
@os-zhuang
os-zhuang merged commit dd9f223 into main Jul 19, 2026
16 checks passed
@os-zhuang
os-zhuang deleted the claude/report-drill-down-range-filter-lxt859 branch July 19, 2026 12:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants