Repository navigation
fix(driver-memory): a preset dateRange on a date field counts the reference zone's calendar days, from UTC westward too - #27341
Conversation
…erence zone's calendar days Move ADR-0053's one window rule (dateRangeWindowBounds and its calendar-day projection) into @objectstack/core beside the dateRange lowering, so the in-memory cube face and service-analytics share one spelling. The memory face asks the driver whether the field is declared date and, if so, filters by the calendar days the preset covers in the reference zone. Claude-Session: https://claude.ai/code/session_01Utp6CbomWvWL9K2F1XBS6p Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 3 package(s): 5 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 5 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 47 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin bb343b94cc4dd44248c326d6aee20d9b84123d03 && git checkout bb343b94cc4dd44248c326d6aee20d9b84123d03
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 8eeb3b3b9255686046a361cf9f9145d6b8e6bfec 4ddf1d4adbccf21612ded5755ac0850165c608fb && git checkout -B drift-repro 8eeb3b3b9255686046a361cf9f9145d6b8e6bfec && git merge --no-ff 4ddf1d4adbccf21612ded5755ac0850165c608fb
node scripts/docs-audit/affected-docs.mjs --json 8eeb3b3b9255686046a361cf9f9145d6b8e6bfec
|
|
domain:server#3 · os-bill · session_01Utp6CXc5hequf76uJfzrdK Contract reviewServed-tier: Face: the ① Derived judgments
② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS Generated by Claude Code |
1 similar comment
|
domain:server#3 · os-bill · session_01Utp6CXc5hequf76uJfzrdK Contract reviewServed-tier: Face: the ① Derived judgments
② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS Generated by Claude Code |
|
domain:server#3 · os-bill · session_01Utp6CXc5hequf76uJfzrdK 席位核对 — ACCEPT ·
|
Requested by Bill · project thread
Fixes #27272
Clause-②: yes (widening)
Metadata-protocol: none
维护者速读
date的字段上时,改为按参考时区的日历日计数;datetime字段仍按时刻比较。这条窗口规则从 service-analytics 挪到@objectstack/core,两边共用同一份。packages/core/src/utils/analytics-date-range.ts末尾新增的两个导出;packages/drivers/driver-memory/src/memory-analytics.ts的parseDateRangeString;packages/services/service-analytics/src/dataset-executor.ts删掉的旧副本。pnpm --filter @objectstack/driver-memory exec vitest run src/memory-analytics-date-range-date-field.test.ts,预期 7 条全过,其中洛杉矶、UTC、上海的 this_quarter 都只列 7/1 和 9/30。What changes
The rule has one home. ADR-0053's window rule (a
datecolumn compares the calendar days the period covers in the reference zone; adatetimecolumn compares instants) was spelled once, inservice-analytics/src/dataset-executor.ts(dateRangeWindowBoundsover the privateinclusiveCalendarDayWindow, PR #27271).@objectstack/driver-memorydepends only oncore,specandtypes, so it cannot import that. Both functions move, unchanged in behaviour, into@objectstack/core'sutils/analytics-date-range.ts, besideresolveAnalyticsDateRangeString, whose header already says the lowering lives there because these two faces cannot import each other.dataset-executor.tsimports both from core and re-exportsdateRangeWindowBounds, so the four service-analytics importers keep their import line. Nothing inpackages/specmoves.The memory face uses it.
MemoryAnalyticsServiceasks the driver whether the time dimension's field is declareddate. If it is, a preset resolves throughdateRangeWindowBounds(window, timezone, true)to the inclusive day pair, and the existing bound construction reads that pair exactly as it reads a caller's bare-day[a, b]($gtefirst day,$ltthe next day after the last). Every other field keeps the instant window it had.One driver accessor. The declared kind lives in
InMemoryDriver's privatetemporalFields(filled bysyncSchema), so the driver gainsisDeclaredDateField(object, field), the same pattern asfilterComparandStorageForm. An object never declared answersfalse: the driver does not guess types from values.Surface widening. The order's file surface was
memory-analytics.ts, its test, the rule's home anddataset-executor.ts. It grew bypackages/drivers/driver-memory/src/memory-driver.ts(the accessor only) andpackages/core/src/utils/analytics-date-range.ts(+ its test), on the seat's call (option A; option B, inferring the kind by probing a comparand's stored shape, was refused as a type guess from a value).Clause-②: yes (widening):@objectstack/coregains the exportsdateRangeWindowBoundsandinclusiveCalendarDayWindow, andInMemoryDrivergains the public methodisDeclaredDateField. Nothing is removed or narrowed. One changeset,patchforcore,driver-memoryandservice-analytics.Tests
packages/drivers/driver-memory/src/memory-analytics-date-range-date-field.test.ts(7): the card's rows (06-30, 07-01, 09-30, 10-01), clock frozen at 2026-09-09, declared viasyncSchema.this_quarterinAmerica/Los_Angeles,UTCandAsia/Shanghaiselects 07-01 and 09-30; Los Angelesthis_monthselects 09-30 and not 10-01; an explicit['2026-07-01', '2026-09-30']is unchanged. A declareddatetimefield keeps the zone-midnight instant pair (both edges pinned one second either side). An undeclared field keeps the instant pair.packages/core/src/utils/analytics-date-range.test.ts(+5): the rule itself, three zones, the non-date arm and the explicit arm.Red before the fix (origin/main ebfadb0)
Shanghai and the datetime and undeclared pins were green before and after. UTC is red too, not only zones west of it: the bare day
2026-07-01sorts before2026-07-01T00:00:00.000Zas text.Ablation (fix committed first, then the face's date branch disabled through scripts/ablation-replace.mjs)
A first attempt used a marker that threw a ReferenceError (red for the wrong reason) and is discarded; the run above is the one that counts.
git diff HEADwas empty after the restore.Package suites (HEAD 4ddf1d4)
Acceptance notes
dateRangeWindowBounds' own contract from analytics: a preset dateRange on a date-typed field counts the wrong calendar days east of UTC (Shanghai this_quarter counts Jun 30, drops Sep 30) #27172 / PR fix(service-analytics): a preset dateRange on a date field counts the reference zone's calendar days, east of UTC too #27271, "a column whose type the caller cannot name answersfalseand keeps the instants", and this driver's rule that it does not guess types from values (memory-temporal.ts). So a bare day stored in a field the driver was never told isdateis still compared to the preset's instants as text. Making it count calendar days would need the face to read the type from the stored value, which is the option the seat refused.$orover both stored forms is unchanged; on a declareddatefield theDatearm reads the day pair as UTC midnights, as it does for a caller's bare-day window.7cd672d6,46faf53d) committed without the session trailer pair; the final commit4ddf1d4acarries it. The branch name is notclaude/issue-*, so it is not force-pushed and history is not rewritten.Verification
Local subset, measured at
4ddf1d4a:node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived 64 families from the 7 changed paths; each ran from the worktree with its exit code captured before any pipe.dispatch-gates --ran: 64 derived, 63 run, 1 NOT-MEASURED, 0 UNRUN
pnpm check:dual-build-cjs-loadsexits 3 (PREREQUISITE NOT MET: it needs every workspace package built, and this worktree built only the three packages' closure). NOT MEASURED locally; CI runs it.node scripts/check-plugin-teardown-shape.mjs --self-testfirst exited 3 on the shallow clone; aftergit fetch origin 621a4876it exits 0 (48 cases).Every other family CI runs is read from this PR's check-runs, not re-run locally.
Generated by Claude Code