Cron scheduler timezone bug: nextRunAtMs incorrectly shifted by +8 hours in v2026.2.6

Resolved 💬 2 comments Opened Feb 8, 2026 by ymzhang10 Closed Mar 9, 2026

Bug Description

When updating a cron job schedule via cron.update, the calculated nextRunAtMs is incorrectly shifted by +8 hours (UTC+8 offset), causing scheduled tasks to be skipped.

Environment

  • OpenClaw Version: 2026.2.6-3 (CLI) / 2026.2.6 (Desktop)
  • OS: macOS Darwin 25.2.0 (arm64)
  • Node.js: v25.5.0
  • System Timezone: Asia/Shanghai (UTC+8)
  • croner version: 10.0.1

Steps to Reproduce

  1. Set system timezone to Asia/Shanghai (UTC+8)
  2. At 21:17 CST (13:17 UTC), update a cron job with schedule:

``json
{
"schedule": {
"kind": "cron",
"expr": "0 8,16,0 * * *",
"tz": "Asia/Shanghai"
}
}
``

  1. The expected next run should be 00:00 CST (16:00 UTC) on the next day
  2. But the actual nextRunAtMs stored is 08:00 CST (00:00 UTC) - exactly 8 hours later

Expected Behavior

| Timestamp | Expected |
|-----------|----------|
| nextRunAtMs | 1770566400000 |
| Local time (CST) | 2026-02-09 00:00:00 |
| UTC | 2026-02-08 16:00:00 |

Actual Behavior

| Timestamp | Actual |
|-----------|--------|
| nextRunAtMs | 1770595200000 |
| Local time (CST) | 2026-02-09 08:00:00 |
| UTC | 2026-02-09 00:00:00 |

The difference is exactly 8 hours (28800000 ms) - the UTC+8 timezone offset.

Root Cause Analysis

I verified that the croner library calculates correctly:

const { Cron } = require('croner');
const now = new Date(1770556659456); // 21:17:39 CST
const cron = new Cron('0 8,16,0 * * *', { timezone: 'Asia/Shanghai' });
const next = cron.nextRun(now);
console.log(next.getTime()); // 1770566400000 ✓ Correct (00:00 CST)

But the Gateway's cron.update returns nextRunAtMs: 1770595200000 (08:00 CST).

This suggests the bug is in how computeNextRunAtMs() or computeJobNextRunAtMs() handles the result - possibly a double timezone conversion or treating CST midnight as UTC midnight.

Impact

  • Scheduled tasks at midnight (or crossing midnight) are skipped
  • Tasks run 8 hours later than expected
  • Affects all users in UTC+ timezones when scheduling jobs that include hour 0

Workaround

Currently, the only workaround is to manually run missed tasks with cron.run --force.

Additional Context

  • The updatedAtMs timestamp is correct (21:17:39 CST)
  • Other jobs with schedules not including hour 0 appear to work correctly
  • The bug was observed when changing from kind: "every" (8h interval) to kind: "cron" expression

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗