← Back to PRs

#15875: fix(cron): normalize seconds to milliseconds in timestamps

by Shuai-DaiDai open 2026-02-14 00:37 View on GitHub →
stale size: XS
## Problem The cron system was treating numeric timestamps inconsistently (#15729). Users passing seconds-based Unix timestamps (10 digits like `1771005600`) would see schedules off by 1000x because JavaScript Date expects milliseconds (13 digits like `1771005600000`). ## Root Cause When users pass `at` or `atMs` as numeric seconds, the code directly used them as milliseconds: - `new Date(1771005600)` produces year 1970 (wrong) - `new Date(1771005600000)` produces year 2026 (correct) ## Solution Add `normalizeTimestampToMs()` helper that detects seconds vs milliseconds: - Values < 1,000,000,000,000 (10^12) are treated as seconds and multiplied by 1000 - Values >= 1,000,000,000,000 are treated as milliseconds and used as-is Files changed: - `src/cron/normalize.ts`: Add helper and use in `coerceSchedule()` - `src/cron/service/store.ts`: Add inline helper in migration code ## Testing Before fix: - Input: `1771005600` (seconds) → Schedules to year 58090 (wrong) After fix: - Input: `1771005600` (seconds) → Correctly schedules to 2026-02-13 18:00:00 UTC - Input: `1771005600000` (ms) → Still works correctly Fixes #15729 <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This change normalizes numeric cron schedule timestamps so seconds-based Unix timestamps are treated as seconds and converted to milliseconds (JS `Date` expects ms). It introduces a `normalizeTimestampToMs()` helper in `src/cron/normalize.ts` for request/input normalization, and applies the same seconds→ms conversion during cron store load/migration in `src/cron/service/store.ts` so persisted `at`/`atMs` values are corrected and stored as ISO strings. No merge-blocking issues were found in the updated normalization or migration paths. <h3>Confidence Score: 5/5</h3> - This PR is safe to merge with minimal risk. - The change is narrowly scoped to timestamp normalization, uses a clear seconds-vs-milliseconds threshold, and is applied consistently in both input normalization and store migration without altering unrelated scheduling logic. - No files require special attention <sub>Last reviewed commit: cf4398b</sub> <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs