mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 19:40:42 +00:00
[AI-assisted] fix(dreaming): use host local timezone for diary timestamps (#65034)
* fix(dreaming): use host local timezone when timezone is not configured When `memory.dreaming.timezone` is unset, `formatNarrativeDate()` previously defaulted to UTC, causing diary timestamps in DREAMS.md and the Control UI to display UTC time as though it were the user's local time. For example, a PDT user seeing 9:46 PM instead of the correct 2:46 PM. Drop the UTC fallback so `Intl.DateTimeFormat` automatically uses the host's timezone when no explicit timezone is provided. Users who have set `agents.defaults.userTimezone` or `dreaming.timezone` are unaffected. Fixes #65027 * docs(changelog): add dreaming timezone entry * Update CHANGELOG.md --------- Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
This commit is contained in:
@@ -16,6 +16,7 @@ Docs: https://docs.openclaw.ai
|
|||||||
- Agents/Anthropic replay: preserve immutable signed-thinking replay safety across stored and live reruns, keep non-thinking embedded `tool_result` user blocks intact, and drop conflicting preserved tool IDs before validation so retries stop degrading into omitted tool calls. (#65126) Thanks @shakkernerd.
|
- Agents/Anthropic replay: preserve immutable signed-thinking replay safety across stored and live reruns, keep non-thinking embedded `tool_result` user blocks intact, and drop conflicting preserved tool IDs before validation so retries stop degrading into omitted tool calls. (#65126) Thanks @shakkernerd.
|
||||||
- Telegram/direct sessions: keep commentary-only assistant fallback payloads out of visible direct delivery, so Codex planning chatter cannot leak into Telegram DMs when a run has no `final_answer` text. (#65112) Thanks @vincentkoc.
|
- Telegram/direct sessions: keep commentary-only assistant fallback payloads out of visible direct delivery, so Codex planning chatter cannot leak into Telegram DMs when a run has no `final_answer` text. (#65112) Thanks @vincentkoc.
|
||||||
- Infra/net: fix multipart FormData fields (including `model`) being silently dropped when a guarded runtime fetch body crosses a FormData implementation boundary, restoring OpenAI audio transcription requests that failed with HTTP 400. (#64349) Thanks @petr-sloup.
|
- Infra/net: fix multipart FormData fields (including `model`) being silently dropped when a guarded runtime fetch body crosses a FormData implementation boundary, restoring OpenAI audio transcription requests that failed with HTTP 400. (#64349) Thanks @petr-sloup.
|
||||||
|
- Dreaming/diary: use the host local timezone for diary timestamps when `dreaming.timezone` is unset, so `DREAMS.md` and the UI stop defaulting to UTC. (#65034) Thanks @neo1027144-creator and @vincentkoc.
|
||||||
- Plugins/memory: restore cached memory capability public artifacts on plugin-registry cache hits so memory-backed artifact surfaces stay visible after warm loads. Thanks @sercada and @vincentkoc.
|
- Plugins/memory: restore cached memory capability public artifacts on plugin-registry cache hits so memory-backed artifact surfaces stay visible after warm loads. Thanks @sercada and @vincentkoc.
|
||||||
- Gateway/cron: preserve requested isolated-agent config across runtime reloads so subagent jobs and heartbeat overrides keep the right workspace and heartbeat settings when the hot-loaded snapshot is stale. Thanks @l0cka and @vincentkoc.
|
- Gateway/cron: preserve requested isolated-agent config across runtime reloads so subagent jobs and heartbeat overrides keep the right workspace and heartbeat settings when the hot-loaded snapshot is stale. Thanks @l0cka and @vincentkoc.
|
||||||
- Cron/isolated sessions: persist the right transcript path for each isolated run, including fresh session rollovers, so cron runs stop appending to stale session files. Thanks @samrusani and @vincentkoc.
|
- Cron/isolated sessions: persist the right transcript path for each isolated run, including fresh session rollovers, so cron runs stop appending to stale session files. Thanks @samrusani and @vincentkoc.
|
||||||
|
|||||||
@@ -122,6 +122,36 @@ describe("formatNarrativeDate", () => {
|
|||||||
expect(date).toContain("2026");
|
expect(date).toContain("2026");
|
||||||
expect(date).toContain("3:00");
|
expect(date).toContain("3:00");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("applies an explicit timezone", () => {
|
||||||
|
// 2026-04-11T21:46:55Z in America/Los_Angeles (PDT, UTC-7) → 2:46 PM
|
||||||
|
const date = formatNarrativeDate(
|
||||||
|
Date.parse("2026-04-11T21:46:55Z"),
|
||||||
|
"America/Los_Angeles",
|
||||||
|
);
|
||||||
|
expect(date).toContain("2:46");
|
||||||
|
expect(date).toContain("PM");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("uses host local timezone when timezone is undefined (#65027)", () => {
|
||||||
|
// Force a non-UTC host timezone so this test is meaningful on UTC CI
|
||||||
|
// runners where the old `?? "UTC"` fallback would silently pass.
|
||||||
|
const originalTZ = process.env.TZ;
|
||||||
|
try {
|
||||||
|
process.env.TZ = "America/Los_Angeles"; // PDT = UTC-7
|
||||||
|
const epochMs = Date.parse("2026-04-11T21:46:55Z");
|
||||||
|
const result = formatNarrativeDate(epochMs);
|
||||||
|
// 21:46 UTC → 14:46 PDT → "2:46 PM"
|
||||||
|
expect(result).toContain("2:46");
|
||||||
|
expect(result).toContain("PM");
|
||||||
|
} finally {
|
||||||
|
if (originalTZ === undefined) {
|
||||||
|
delete process.env.TZ;
|
||||||
|
} else {
|
||||||
|
process.env.TZ = originalTZ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("buildDiaryEntry", () => {
|
describe("buildDiaryEntry", () => {
|
||||||
|
|||||||
@@ -231,7 +231,7 @@ export function extractNarrativeText(messages: unknown[]): string | null {
|
|||||||
|
|
||||||
export function formatNarrativeDate(epochMs: number, timezone?: string): string {
|
export function formatNarrativeDate(epochMs: number, timezone?: string): string {
|
||||||
const opts: Intl.DateTimeFormatOptions = {
|
const opts: Intl.DateTimeFormatOptions = {
|
||||||
timeZone: timezone ?? "UTC",
|
timeZone: timezone,
|
||||||
year: "numeric",
|
year: "numeric",
|
||||||
month: "long",
|
month: "long",
|
||||||
day: "numeric",
|
day: "numeric",
|
||||||
|
|||||||
Reference in New Issue
Block a user