Skip to content

Commit 0138641

Browse files
docs(jobs): a job body's default locale and time zone are the server's (#29355)
<!-- claude-projects-attribution: {"github_login":"marchtian"} --> _Requested by **田騏** · [project thread](https://claude.ai/code/project/chan_01VmuUhXU9SSUzqJYyXSmYSi?thread=cmsg_01VmuUhXU9SSUzqJYyXSmYSi9paTx1Lu8ENYwwssthfK3h)_ Fixes #29202 Clause-②: no Metadata-protocol: none ## 维护者速读 - 改了什么:定时任务文档 `jobs.mdx` 在 `Intl.DateTimeFormat` 那条说明里补两句话:不传语言和 `timeZone` 时用的是服务器的默认语言和时区,要稳定输出就显式传 `timeZone`(和语言)。 - 为什么改:开发者本地跑和服务器跑会得到不同的日期,文档之前没提醒;这是 #29031 合约复审点名的后续。 - 风险与回滚:纯文档,不改代码、不发布任何包;回滚即还原这 5 行。 - 先看:`content/docs/automation/jobs.mdx` 第 199–203 行(新增的两句与示例)。 - 两分钟验证:打开文档站「Jobs」页的沙箱一节,`Intl.DateTimeFormat` 那条下应看到 “server's default locale and time zone” 与 `{ timeZone: 'UTC' }` 示例。 - 需要你做的:无,席位落地。 ## What changes One addition to the `Intl.DateTimeFormat` bullet in `content/docs/automation/jobs.mdx` (+5 / -0): a formatter built with no locale or `timeZone` uses the server's default locale and time zone, and its `resolvedOptions()` reports them; a body should pass `timeZone` (and a locale) for output that does not depend on where it runs, with `new Intl.DateTimeFormat('en-US', { timeZone: 'UTC' })` as the example. No code change. ## Tests None owed: docs only, no tested behaviour changes. The statement was measured before it was written (below). ## Acceptance notes - The wiring that backs the sentence: the VM-side constructor in `packages/runtime/src/sandbox/sandbox-intl.ts` snapshots `locales` / `options`; with neither given the snapshot is empty, `readSnapshot` hands `undefined` / `undefined` to the host, and `installSandboxIntl` builds `new Intl.DateTimeFormat(locales, options)` with the host's own `Intl`, so the host's defaults apply. `QuickJSScriptRunner.execute()` in `packages/runtime/src/sandbox/quickjs-runner.ts` calls `installSandboxIntl(vm)` for every body kind. - Hook and action pages (`content/docs/automation/hooks.mdx`, `content/docs/automation/hook-bodies.mdx`, `content/docs/ui/actions.mdx`) do not carry the `Intl.DateTimeFormat` bullet, so there is nothing to mirror there; the jobs bullet already says hook and action bodies get the same formatter. - No changeset: `content/docs` ships in no package's `files[]`, so `skip-changeset`. ## Verification <details><summary>Measured: a no-option formatter answers the host's locale and zone</summary> A scratch script installed `installSandboxIntl` into a fresh QuickJS context (the same call `execute()` makes) and evaluated `new Intl.DateTimeFormat().resolvedOptions()` and `.format(0)` inside the VM, beside a formatter given `'en-US', { timeZone: 'UTC' }`, under three host settings: | Host `TZ` / locale | No-option `resolvedOptions()` | No-option `format(0)` | Pinned `format(0)` | |:--|:--|:--|:--| | `Asia/Tokyo` / `de_DE` | `de-DE`, `Asia/Tokyo` | `1.1.1970` | `1/1/1970` | | `America/New_York` / `de_DE` | `de-DE`, `America/New_York` | `31.12.1969` | `1/1/1970` | | `Asia/Tokyo` / `en_GB` | `en-GB`, `Asia/Tokyo` | `01/01/1970` | `1/1/1970` | Each no-option row equals the host's own `new Intl.DateTimeFormat().resolvedOptions()` in the same process; the pinned formatter answers the same in all three. The script was not committed. </details> <details><summary>Derived gates at 7dc9c8c (after merging origin/main a2fcede)</summary> `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack`: 43 commands. All 43 ran, each exit code captured before any pipe: 43 at exit 0. Four first refused with exit 3 (PREREQUISITE NOT MET: `@objectstack/lint` / `@objectstack/formula` / `@objectstack/client-react` not built); after `pnpm --filter '@objectstack/lint...' --filter '@objectstack/client-react...' build` (VERDICT command-exit 0) each re-ran at exit 0: `check:doc-formula-expressions`, `check:doc-security-posture`, `check:skill-examples`, `check:docs-transcript-drift`. `--ran` reconciliation: 43 derived, 43 run, 0 NOT-MEASURED, 0 UNRUN (a derived zero: all 43 recorded an exit code). NOT MEASURED locally, left to CI: `ci.yml · Build Docs` and `ci.yml · Plan Test Core shards`, and the type-check lanes the derivation lists. </details> 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude <noreply@anthropic.com>
1 parent 85f7a0d commit 0138641

1 file changed

Lines changed: 5 additions & 0 deletions

File tree

‎content/docs/automation/jobs.mdx‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,11 @@ What running in the sandbox means for the code in `source`:
196196
`resolvedOptions`), and answers exactly as the server's own does, so a body can
197197
find the calendar date or period of an instant in a named IANA zone:
198198
`new Intl.DateTimeFormat('en-CA', { timeZone: 'Asia/Shanghai', year: 'numeric', month: '2-digit', day: '2-digit' }).format(Date.now())`.
199+
With no locale or `timeZone`, a formatter uses the server's default locale and
200+
time zone (its `resolvedOptions()` reports them), so the same body can print a
201+
different date on your machine than on the server. Pass `timeZone`, and a
202+
locale, for output that does not depend on where the body runs:
203+
`new Intl.DateTimeFormat('en-US', { timeZone: 'UTC' })`.
199204
Nothing else of `Intl` is there (`Intl.NumberFormat` is `undefined`); test for
200205
it with `typeof Intl.DateTimeFormat === 'function'`. Hook and action bodies run
201206
in the same sandbox and get the same `Intl.DateTimeFormat`.

0 commit comments

Comments
 (0)