mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-04 01:34:06 +00:00
fix(auto-reply): guard date stamp formatting
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { normalizeTimestamp } from "./date-time.js";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { formatDateStamp, normalizeTimestamp } from "./date-time.js";
|
||||
|
||||
describe("normalizeTimestamp", () => {
|
||||
it("normalizes numeric second and millisecond timestamps", () => {
|
||||
@@ -18,3 +18,15 @@ describe("normalizeTimestamp", () => {
|
||||
expect(normalizeTimestamp("999999999999999999999999")).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe("formatDateStamp", () => {
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it("falls back when nowMs is outside Date range", () => {
|
||||
vi.spyOn(Date, "now").mockReturnValue(Date.UTC(2026, 4, 30, 12, 0, 0));
|
||||
|
||||
expect(formatDateStamp(8_640_000_000_000_001, "UTC")).toBe("2026-05-30");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { asDateTimestampMs } from "../shared/number-coercion.js";
|
||||
|
||||
export type TimeFormatPreference = "auto" | "12" | "24";
|
||||
export type ResolvedTimeFormat = "12" | "24";
|
||||
@@ -40,6 +41,24 @@ export function resolveUserTimeFormat(preference?: TimeFormatPreference): Resolv
|
||||
return cachedTimeFormat;
|
||||
}
|
||||
|
||||
export function formatDateStamp(nowMs: number, timeZone: string): string {
|
||||
const timestampMs = asDateTimestampMs(nowMs) ?? Date.now();
|
||||
const date = new Date(timestampMs);
|
||||
const parts = new Intl.DateTimeFormat("en-US", {
|
||||
timeZone,
|
||||
year: "numeric",
|
||||
month: "2-digit",
|
||||
day: "2-digit",
|
||||
}).formatToParts(date);
|
||||
const year = parts.find((part) => part.type === "year")?.value;
|
||||
const month = parts.find((part) => part.type === "month")?.value;
|
||||
const day = parts.find((part) => part.type === "day")?.value;
|
||||
if (year && month && day) {
|
||||
return `${year}-${month}-${day}`;
|
||||
}
|
||||
return date.toISOString().slice(0, 10);
|
||||
}
|
||||
|
||||
export function normalizeTimestamp(
|
||||
raw: unknown,
|
||||
): { timestampMs: number; timestampUtc: string } | undefined {
|
||||
|
||||
@@ -2,7 +2,7 @@ import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { resolveAgentContextLimits } from "../../agents/agent-scope.js";
|
||||
import { resolveCronStyleNow } from "../../agents/current-time.js";
|
||||
import { resolveUserTimezone } from "../../agents/date-time.js";
|
||||
import { formatDateStamp, resolveUserTimezone } from "../../agents/date-time.js";
|
||||
import type { OpenClawConfig } from "../../config/types.openclaw.js";
|
||||
import { openRootFile } from "../../infra/boundary-file-read.js";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../../shared/string-coerce.js";
|
||||
@@ -40,22 +40,6 @@ function matchesSectionSet(sectionNames: string[], expectedSections: string[]):
|
||||
return counts.size === 0;
|
||||
}
|
||||
|
||||
function formatDateStamp(nowMs: number, timezone: string): string {
|
||||
const parts = new Intl.DateTimeFormat("en-US", {
|
||||
timeZone: timezone,
|
||||
year: "numeric",
|
||||
month: "2-digit",
|
||||
day: "2-digit",
|
||||
}).formatToParts(new Date(nowMs));
|
||||
const year = parts.find((p) => p.type === "year")?.value;
|
||||
const month = parts.find((p) => p.type === "month")?.value;
|
||||
const day = parts.find((p) => p.type === "day")?.value;
|
||||
if (year && month && day) {
|
||||
return `${year}-${month}-${day}`;
|
||||
}
|
||||
return new Date(nowMs).toISOString().slice(0, 10);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read critical sections from workspace AGENTS.md for post-compaction injection.
|
||||
* Returns formatted system event text, or null if no AGENTS.md or no relevant sections.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { resolveUserTimezone } from "../../agents/date-time.js";
|
||||
import { formatDateStamp, resolveUserTimezone } from "../../agents/date-time.js";
|
||||
import type { OpenClawConfig } from "../../config/config.js";
|
||||
import { openRootFile } from "../../infra/boundary-file-read.js";
|
||||
import { uniqueStrings } from "../../shared/string-normalization.js";
|
||||
@@ -64,22 +64,6 @@ function resolveStartupContextLimits(cfg?: OpenClawConfig) {
|
||||
};
|
||||
}
|
||||
|
||||
function formatDateStamp(nowMs: number, timezone: string): string {
|
||||
const parts = new Intl.DateTimeFormat("en-US", {
|
||||
timeZone: timezone,
|
||||
year: "numeric",
|
||||
month: "2-digit",
|
||||
day: "2-digit",
|
||||
}).formatToParts(new Date(nowMs));
|
||||
const year = parts.find((part) => part.type === "year")?.value;
|
||||
const month = parts.find((part) => part.type === "month")?.value;
|
||||
const day = parts.find((part) => part.type === "day")?.value;
|
||||
if (year && month && day) {
|
||||
return `${year}-${month}-${day}`;
|
||||
}
|
||||
return new Date(nowMs).toISOString().slice(0, 10);
|
||||
}
|
||||
|
||||
function shiftDateStampByCalendarDays(stamp: string, offsetDays: number): string {
|
||||
const [yearRaw, monthRaw, dayRaw] = stamp.split("-").map((part) => Number.parseInt(part, 10));
|
||||
if (!yearRaw || !monthRaw || !dayRaw) {
|
||||
|
||||
Reference in New Issue
Block a user