From dfc835f00aad532b77dde1914adf738d44d45ee0 Mon Sep 17 00:00:00 2001 From: Byron Torres <43079131+torresjrjr@users.noreply.github.com> Date: Sat, 20 Jul 2019 17:21:59 +0100 Subject: [PATCH] Support for tz-aware datetime.datetime objects ## Original issue ## Issue: python-telegram-bot#1409 version: 12.0.0b1 ## Changes ## The `._put()` method can now accept utc_offset-aware/timezone-aware `datetime.datetime` objects. This helps bots to be hosted on a server with any timezone without complications. To convert datetimes to UTC, a "UTC" subclass of the `datetime.tzinfo` class was added, and used in `._put()`. ## Other options considered ## - Changing all the `.now()` comparisons in `._put()` to `.utcnow()`. This was not chosen, since it would cause a major compatibility issue. Bots would have to be rewritten to pass in UTC datetimes, instead of local (computer time) datetimes, into the jobqueue.run_once and other methods. This would likely be unwanted behaivour. --- telegram/ext/jobqueue.py | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/telegram/ext/jobqueue.py b/telegram/ext/jobqueue.py index e3cfacfd9ae..06cd42055e0 100644 --- a/telegram/ext/jobqueue.py +++ b/telegram/ext/jobqueue.py @@ -36,6 +36,22 @@ class Days(object): EVERY_DAY = tuple(range(7)) +class UTC(datetime.tzinfo): + """UTC""" + + ZERO = datetime.timedelta(0) + HOUR = datetime.timedelta(hours=1) + + def utcoffset(self, dt): + return ZERO + + def tzname(self, dt): + return "UTC" + + def dst(self, dt): + return ZERO + + class JobQueue(object): """This class allows you to periodically perform tasks with the bot. @@ -77,7 +93,11 @@ def _put(self, job, next_t=None, last_t=None): raise ValueError('next_t is None') if isinstance(next_t, datetime.datetime): - next_t = (next_t - datetime.datetime.now()).total_seconds() + if next_t.tzinfo == None: + next_t = (next_t - datetime.datetime.now()).total_seconds() + else: + next_t = next_t.astimezone(UTC()).replace(tzinfo=None) + next_t = (next_t - datetime.datetime.utcnow()).total_seconds() elif isinstance(next_t, datetime.time): next_datetime = datetime.datetime.combine(datetime.date.today(), next_t)