1

I'm trying to run a job ever day at 8:00 AM at timezone('Asia/Calcutta'), so i started using python scheduler. sample snippet

import schedule
import time

def job(t):
    print "I'm working...", t
    return

schedule.every().day.at("08:00").do(job,'It is 08:00')

while True:
    schedule.run_pending()
    time.sleep(30) # wait one minute

this snippets works very well if a execute in Indian servers, but if i run in COLAB or AWS (which are in different timezone), job start at 8:00 am based on that particular time zone. But i would like to make code to run every day 8:00 am on this timezone('Asia/Calcutta'), irrespective of the server time zone. i gone through different article from stackoverflow related to timezones, getting offset and changing 8:00 am to something like 8:00 + some offset 4:30 hrs. but did notwork.

  1. looking for best way to run python code on anyserver/any timezone, but scheduler will trigger in timezone('Asia/Calcutta') this timezon.

  2. is there any way to change datetime timezone on thread level or full python process level (only for that script/thread, not system level), so i want to change timezone once in python, and after that where every i call datetime.now(), it should give time as per new timzone,

       eastern = timezone('Asia/Calcutta')
       # naive datetime
       naive_dt = datetime.now()
       # localized datetime
       loc_dt = datetime.now(eastern)
       print(naive_dt.strftime(fmt))
    
       print(loc_dt.strftime(fmt))
    

based on this (answer) not interested to change system files, looking pythonic way

bommina
  • 307
  • 4
  • 16

1 Answers1

3

If you are looking for a scheduler with timezone support in mind, you might be interested in the scheduler library. An example for a similar situation as you described can be found in the documentation. I modified it below to suit your question and additionally added a second Job with an independant timezone for better demonstration.

Disclosure: I'm one of the authors of the scheduler library

Question 1

Setup your server and job timezones and create a payload function.

import datetime as dt
import time
from scheduler import Scheduler
import pytz 

TZ_SERVER = dt.timezone.utc  # can be any valid timezone

TZ_IST = pytz.timezone('Asia/Calcutta')  # IST - India Standard Time
TZ_CEST = pytz.timezone('Europe/Berlin')  # CEST - Central European Summer Time

def task(tzinfo):
    current_time = dt.datetime.now(tzinfo)
    print(f"I'm working... {current_time!s}")

Create a Scheduler instance and schedule recurring daily jobs with specified times and timezones:

schedule = Scheduler(tzinfo=TZ_SERVER)

trigger_ist = dt.time(hour=8, tzinfo=TZ_IST)
schedule.daily(trigger_ist, task, args=(TZ_IST,))

trigger_cest = dt.time(hour=8, tzinfo=TZ_CEST)
job_cest = schedule.daily(trigger_cest, task, args=(TZ_CEST,))

Show a simple overview of the schedule.

print(schedule)
max_exec=inf, tzinfo=UTC, priority_function=linear_priority_function, #jobs=2

type     function         due at              tzinfo          due in      attempts weight
-------- ---------------- ------------------- ------------ --------- ------------- ------
DAILY    task(..)         2021-07-20 08:00:00 IST            2:36:42         0/inf      1
DAILY    task(..)         2021-07-20 08:00:00 CEST           6:06:42         0/inf      1

Create your execution loop analogous to the schedule library:

while True:
    schedule.exec_jobs()
    time.sleep(60)  # wait one minute

Once the payload function is called you should see something similar to below.

I'm working... 2021-07-20 08:00:33.173469+05:30

Question 2

I'm unsure if I understand your second question, but it is alway possible to cast one datetime.datetime object with a timezone into another datetime.datetime object with another timezone. E.g. you can do:

now_cest = dt.datetime.now(TZ_CEST)
now_ist = now_cest.astimezone(TZ_IST)
F. Preiss
  • 46
  • 4
  • it's bad checked your answer after a 1 year, i think i have got solution at that point of time same as what you have mentioned thnx. – bommina May 27 '22 at 03:42