datetime said midnight. Server logged 5 AM.
Built a scheduler that ran tasks at midnight. Worked fine on my laptop. Deployed to AWS and everything started running at 5 AM.
What happened
I was scheduling database backups using Python's datetime. Simple code:
from datetime import datetime, time
import schedule
def backup_database():
print(f"Backup started at {datetime.now()}")
# database backup logic here
schedule.every().day.at("00:00").do(backup_database)
while True:
schedule.run_pending()
time.sleep(60)
Ran it locally (Peru timezone UTC-5), worked perfect. Midnight backups like clockwork.
Deployed to AWS EC2 instance (UTC timezone). Checked logs next morning and backups ran at 5 AM local time.
Why it broke
The schedule library uses local server time. My EC2 instance defaulted to UTC. When I said "00:00", it scheduled for UTC midnight, which is 5 AM Peru time.
I assumed datetime was timezone aware. It's not unless you explicitly make it.
What fixed it
Stopped trusting naive datetime objects. Started forcing timezone awareness:
from datetime import datetime
from zoneinfo import ZoneInfo
import schedule
def backup_database():
peru_tz = ZoneInfo("America/Lima")
now = datetime.now(peru_tz)
print(f"Backup started at {now.strftime('%Y-%m-%d %H:%M %Z')}")
# database backup logic
# Get current hour in Peru time
peru_tz = ZoneInfo("America/Lima")
current_hour = datetime.now(peru_tz).hour
# Schedule for midnight Peru time
schedule.every().day.at("00:00").do(backup_database)
But that still used server local time for scheduling. Real fix was converting target time to server timezone:
from datetime import datetime, time as dt_time
from zoneinfo import ZoneInfo
import schedule
def backup_database():
peru_tz = ZoneInfo("America/Lima")
print(f"Backup at {datetime.now(peru_tz)}")
# Convert midnight Peru to UTC for scheduling
peru_tz = ZoneInfo("America/Lima")
utc_tz = ZoneInfo("UTC")
midnight_peru = datetime.now(peru_tz).replace(hour=0, minute=0, second=0)
midnight_utc = midnight_peru.astimezone(utc_tz)
schedule.every().day.at(midnight_utc.strftime("%H:%M")).do(backup_database)
Now it schedules at 05:00 UTC (which is midnight Peru). Logs show correct time.
Switched to APScheduler eventually because it handles timezones better out of the box. Still annoyed I spent a day debugging something that obvious tho.
Python datetime being naive by default feels like a design mistake honestly. Or maybe I just suck at reading docs.
Top comments (0)