openclaw/src/cron/schedule.ts
Tes Sal 8d34bcf32e feat: use userTimezone as default for cron schedules
Fixes #3318

Previously, cron schedules without an explicit `tz` field would use
the system timezone, which could cause confusion if the server is in
a different timezone than the user.

Now, `agents.defaults.userTimezone` from the config is used as the
default timezone for cron schedule computations when the schedule
doesn't specify its own `tz`.

Changes:
- Added `defaultTimezone` option to `computeNextRunAtMs()`
- Added `defaultTimezone` to `CronServiceDeps`
- Gateway passes `userTimezone` from config to cron service
- All job computations now respect the default timezone
2026-01-28 13:03:17 +00:00

38 lines
1.2 KiB
TypeScript

import { Cron } from "croner";
import type { CronSchedule } from "./types.js";
export type ComputeNextRunOpts = {
/** Default timezone to use when schedule.tz is not specified. */
defaultTimezone?: string;
};
export function computeNextRunAtMs(
schedule: CronSchedule,
nowMs: number,
opts?: ComputeNextRunOpts,
): number | undefined {
if (schedule.kind === "at") {
return schedule.atMs > nowMs ? schedule.atMs : undefined;
}
if (schedule.kind === "every") {
const everyMs = Math.max(1, Math.floor(schedule.everyMs));
const anchor = Math.max(0, Math.floor(schedule.anchorMs ?? nowMs));
if (nowMs < anchor) return anchor;
const elapsed = nowMs - anchor;
const steps = Math.max(1, Math.floor((elapsed + everyMs - 1) / everyMs));
return anchor + steps * everyMs;
}
const expr = schedule.expr.trim();
if (!expr) return undefined;
// Use schedule.tz if specified, otherwise fall back to default timezone
const timezone = schedule.tz?.trim() || opts?.defaultTimezone?.trim() || undefined;
const cron = new Cron(expr, {
timezone,
catch: false,
});
const next = cron.nextRun(new Date(nowMs));
return next ? next.getTime() : undefined;
}