A cron replacement that handles multiple time zones

Solution 1:

fcron supports this feature.

From the documentation of the "timezone" option in fcrontab(5):

Run the job in the given time zone. timezone-name is a string which is valid for the environment variable TZ: see the documentation of your system for more details. For instance, "Europe/Paris" is valid on a Linux system. This option handles daylight saving time changes correctly. The TZ environment variable is set to the value of timezone when a job defining this option is run.

Solution 2:

I think you're trying to have it both ways and the reality is that you just can't. If you want a job to run at 8 AM local time, for example, regardless of whether daylight saving is active then you either run your system (and cron) in local time and don't do seasonal edits or you run it in UTC (not GMT) and do seasonal edits. If you want your jobs to run at the same UTC, regardless, then you run cron according to UTC and there's nothing more to do.

If what you want is for a user to be able to schedule a cron job according to his local time zone and not have him have to think about conversions for his convenience then you write a conversion script that accepts a cron spec and a time zone then does the conversion to UTC behind the scenes and edits the crontab for him. It could even be a two-way conversion to handle changes to existing entries.

It will be helpful if you tell us what you're actually trying to accomplish.


Solution 3:

You could write yourself a little wrapper that takes three args:

  • Target timezone hour to match
  • Target timezone
  • Command to run if target tz hour matches current hour (in target tz).

Then just put that wrapper line in your crontab to run hourly:

python tz_wrapper.py 14 "US/Mountain" "echo 'hi'"

Simple python version:

#!/usr/bin/python
import sys, os, datetime
import pytz

arg_hour = sys.argv[1]
arg_timezone = sys.argv[2]
arg_cmd = sys.argv[3]

target_tz = pytz.timezone(arg_timezone)
target_hour = pytz.utc.localize(datetime.datetime.utcnow()).astimezone(target_tz).strftime("%H")

if target_hour == str(arg_hour):
    os.system(arg_cmd)