Bug Description
cron.jobs.get_due_jobs() can incorrectly skip jobs when next_run_at is a legacy naive timestamp and HERMES_TIMEZONE differs from system local timezone.
Root Cause
_ensure_aware() attaches Hermes timezone directly to naive datetimes via replace(tzinfo=...).
For naive values that were originally system-local wall time, this reinterpretation shifts absolute time and can make overdue jobs appear not due.
Reproduction
- Set HERMES_TIMEZONE to a timezone different from system local timezone
- Store a naive next_run_at (legacy format, no offset)
- Call get_due_jobs()
- A timestamp created as 5 minutes in the past can be evaluated as not due
Expected
Legacy naive timestamps should be interpreted as system-local wall time, then converted to Hermes timezone for comparison.
Proposed Fix
In _ensure_aware():
- if datetime is naive: attach system local timezone via datetime.now().astimezone().tzinfo, then convert to Hermes timezone
- if datetime already aware: normalize to Hermes timezone via astimezone
Patch is ready in branch fix/cron-naive-timestamp-due-jobs.
Bug Description
cron.jobs.get_due_jobs() can incorrectly skip jobs when next_run_at is a legacy naive timestamp and HERMES_TIMEZONE differs from system local timezone.
Root Cause
_ensure_aware() attaches Hermes timezone directly to naive datetimes via replace(tzinfo=...).
For naive values that were originally system-local wall time, this reinterpretation shifts absolute time and can make overdue jobs appear not due.
Reproduction
Expected
Legacy naive timestamps should be interpreted as system-local wall time, then converted to Hermes timezone for comparison.
Proposed Fix
In _ensure_aware():
Patch is ready in branch fix/cron-naive-timestamp-due-jobs.