When datetime.utcnow() (naive) was passed as after=, astimezone() treated it as system-local time (Beijing), causing next_run_at to be calculated incorrectly. Now naive datetimes are explicitly localized to UTC first. Also replaced deprecated datetime.utcnow() with aware UTC equivalent. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>