diff --git a/bot.py b/bot.py index bf95380..e04420e 100644 --- a/bot.py +++ b/bot.py @@ -16,8 +16,7 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -from datetime import datetime -from datetime import timedelta +from datetime import datetime, timedelta, timezone import logging from queue import Queue import re @@ -277,8 +276,8 @@ class Bot(threading.Thread): if len(self.events) > 0: logger.debug("Update timer: next event in %d seconds", self.events[0].time_left.seconds) - if datetime.now() + timedelta(seconds=5) >= self.events[0].current: - while datetime.now() < self.events[0].current: + if datetime.now(timezone.utc) + timedelta(seconds=5) >= self.events[0].current: + while datetime.now(timezone.utc) < self.events[0].current: time.sleep(0.6) self._end_event_timer() else: @@ -292,7 +291,7 @@ class Bot(threading.Thread): def _end_event_timer(self): """Function called at the end of the event timer""" - while len(self.events) > 0 and datetime.now() >= self.events[0].current: + while len(self.events) > 0 and datetime.now(timezone.utc) >= self.events[0].current: evt = self.events.pop(0) self.cnsr_queue.put_nowait(EventConsumer(evt)) self._launch_consumers() diff --git a/event.py b/event.py index fc90785..857a51a 100644 --- a/event.py +++ b/event.py @@ -16,7 +16,7 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -from datetime import datetime, timedelta +from datetime import datetime, timedelta, timezone class ModuleEvent: @@ -77,7 +77,7 @@ class ModuleEvent: """Return the date of the near check""" if self.times != 0: if self._end is None: - self._end = datetime.now() + self.offset + self.interval + self._end = datetime.now(timezone.utc) + self.offset + self.interval return self._end return None @@ -88,7 +88,7 @@ class ModuleEvent: if self.times != 0: if self._end is None: return self.current - elif self._end < datetime.now(): + elif self._end < datetime.now(timezone.utc): self._end += self.interval return self._end return None @@ -98,7 +98,7 @@ class ModuleEvent: def time_left(self): """Return the time left before/after the near check""" if self.current is not None: - return self.current - datetime.now() + return self.current - datetime.now(timezone.utc) return 99999 #TODO: 99999 is not a valid time to return diff --git a/modules/alias.py b/modules/alias.py index e790a86..370ac1d 100644 --- a/modules/alias.py +++ b/modules/alias.py @@ -4,7 +4,7 @@ import re import sys -from datetime import datetime +from datetime import datetime, timezone from hooks import hook @@ -41,9 +41,7 @@ def get_variable(name, msg=None): elif name == "chan" or name == "channel": return msg.channel elif name == "date": - now = datetime.now() - return ("%d/%d/%d %d:%d:%d"%(now.day, now.month, now.year, now.hour, - now.minute, now.second)) + return datetime.now(timezone.utc).strftime("%c") elif name in DATAS.getNode("variables").index: return DATAS.getNode("variables").index[name]["value"] else: diff --git a/modules/bonneannee.py b/modules/bonneannee.py index f50c9b2..5597b96 100644 --- a/modules/bonneannee.py +++ b/modules/bonneannee.py @@ -2,7 +2,7 @@ """Wishes Happy New Year when the time comes""" -from datetime import datetime +from datetime import datetime, timezone from hooks import hook from tools.countdown import countdown_format @@ -11,15 +11,15 @@ nemubotversion = 3.4 from more import Response -yr = datetime.today().year -yrn = datetime.today().year + 1 +yr = datetime.now(timezone.utc).year +yrn = datetime.now(timezone.utc).year + 1 def load(context): - d = datetime(yrn, 1, 1, 0, 0, 0) - datetime.now() + d = datetime(yrn, 1, 1, 0, 0, 0) - datetime.now(timezone.utc) add_event(ModuleEvent(interval=0, offset=d.total_seconds(), call=bonneannee)) def bonneannee(): - txt = "Bonne année %d !" % datetime.today().year + txt = "Bonne année %d !" % yrn print (txt) send_response("localhost:2771", Response(txt, "#epitagueule")) send_response("localhost:2771", Response(txt, "#yaka")) @@ -31,7 +31,7 @@ def bonneannee(): @hook("cmd_hook", "newyear") @hook("cmd_hook", str(yrn), yrn) def cmd_newyear(msg, yr): - return Response(countdown_format(datetime(yr, 1, 1, 0, 0, 1), + return Response(countdown_format(datetime(yr, 1, 1, 0, 0, 1, 0, timezone.utc), "Il reste %s avant la nouvelle année.", "Nous faisons déjà la fête depuis %s !"), channel=msg.channel) @@ -43,7 +43,7 @@ def cmd_timetoyear(msg, cur): if yr == cur: return None - return Response(countdown_format(datetime(yr, 1, 1, 0, 0, 1), + return Response(countdown_format(datetime(yr, 1, 1, 0, 0, 1, 0, timezone.utc), "Il reste %s avant %d." % ("%s", yr), "Le premier janvier %d est passé depuis %s !" % (yr, "%s")), channel=msg.channel) diff --git a/modules/events.py b/modules/events.py index a17227c..af20867 100644 --- a/modules/events.py +++ b/modules/events.py @@ -5,8 +5,7 @@ import imp import re import sys -from datetime import timedelta -from datetime import datetime +from datetime import datetime, timedelta, timezone import time import threading import traceback @@ -32,7 +31,7 @@ def load(context): if DATAS.index[evt].hasAttribute("end"): event = ModuleEvent(call=fini, call_data=dict(strend=DATAS.index[evt])) event._end = DATAS.index[evt].getDate("end") - idt = context.add_event(event) + idt = add_event(event) if idt is not None: DATAS.index[evt]["id"] = idt @@ -44,8 +43,8 @@ def fini(d, strend): @hook("cmd_hook", "goûter") def cmd_gouter(msg): - ndate = datetime.today() - ndate = datetime(ndate.year, ndate.month, ndate.day, 16, 42) + ndate = datetime.now(timezone.utc) + ndate = datetime(ndate.year, ndate.month, ndate.day, 16, 42, 0, 0, timezone.utc) return Response(countdown_format(ndate, "Le goûter aura lieu dans %s, préparez vos biscuits !", "Nous avons %s de retard pour le goûter :("), @@ -53,8 +52,8 @@ def cmd_gouter(msg): @hook("cmd_hook", "week-end") def cmd_we(msg): - ndate = datetime.today() + timedelta(5 - datetime.today().weekday()) - ndate = datetime(ndate.year, ndate.month, ndate.day, 0, 0, 1) + ndate = datetime.now(timezone.utc) + timedelta(5 - datetime.today().weekday()) + ndate = datetime(ndate.year, ndate.month, ndate.day, 0, 0, 1, 0, timezone.utc) return Response(countdown_format(ndate, "Il reste %s avant le week-end, courage ;)", "Youhou, on est en week-end depuis %s."), @@ -95,14 +94,14 @@ def start_countdown(msg): if result2 is None or result2.group(4) is None: yea = now.year else: yea = int(result2.group(4)) if result2 is not None and result3 is not None: - strnd["end"] = datetime(yea, int(result2.group(3)), int(result2.group(2)), hou, minu, sec) + strnd["end"] = datetime(yea, int(result2.group(3)), int(result2.group(2)), hou, minu, sec, timezone.utc) elif result2 is not None: - strnd["end"] = datetime(int(result2.group(4)), int(result2.group(3)), int(result2.group(2))) + strnd["end"] = datetime(int(result2.group(4)), int(result2.group(3)), int(result2.group(2)), 0, 0, 0, timezone.utc) elif result3 is not None: if hou * 3600 + minu * 60 + sec > now.hour * 3600 + now.minute * 60 + now.second: - strnd["end"] = datetime(now.year, now.month, now.day, hou, minu, sec) + strnd["end"] = datetime(now.year, now.month, now.day, hou, minu, sec, timezone.utc) else: - strnd["end"] = datetime(now.year, now.month, now.day + 1, hou, minu, sec) + strnd["end"] = datetime(now.year, now.month, now.day + 1, hou, minu, sec, timezone.utc) evt._end = strnd.getDate("end") strnd["id"] = add_event(evt) except: diff --git a/modules/sleepytime.py b/modules/sleepytime.py index 9cb1169..b662878 100644 --- a/modules/sleepytime.py +++ b/modules/sleepytime.py @@ -4,8 +4,7 @@ import re import imp -from datetime import datetime -from datetime import timedelta +from datetime import datetime, timedelta, timezone from hooks import hook @@ -22,9 +21,9 @@ def cmd_sleep(msg): msg.cmds[1]) is not None: # First, parse the hour p = re.match("([0-9]{1,2})[h':.,-]([0-9]{1,2})?[m':.,-]?", msg.cmds[1]) - f = [datetime(datetime.today().year, - datetime.today().month, - datetime.today().day, + f = [datetime(datetime.now(timezone.utc).year, + datetime.now(timezone.utc).month, + datetime.now(timezone.utc).day, hour=int(p.group(1)))] if p.group(2) is not None: f[0] += timedelta(minutes=int(p.group(2))) @@ -37,7 +36,7 @@ def cmd_sleep(msg): # Just get awake times else: - f = [datetime.now() + timedelta(minutes=15)] + f = [datetime.now(timezone.utc) + timedelta(minutes=15)] g = list() for i in range(0,6): f.append(f[i] + timedelta(hours=1,minutes=30)) diff --git a/modules/worldcup.py b/modules/worldcup.py index c829bc3..cd093ab 100644 --- a/modules/worldcup.py +++ b/modules/worldcup.py @@ -2,7 +2,7 @@ """The 2014 football worldcup module""" -import datetime +from datetime import datetime, timezone import json import re from urllib.parse import quote @@ -32,7 +32,7 @@ def start_watch(msg): w["channel"] = msg.channel w["proprio"] = msg.nick w["sender"] = msg.sender - w["start"] = datetime.datetime.now() + w["start"] = datetime.now(timezone.utc) DATAS.addChild(w) save() raise IRCException("This channel is now watching world cup events!") @@ -125,7 +125,7 @@ def txt_event(e): return "%se minutes : %s %s (%s)" % (e["time"], detail_event(e["type_of_event"]), e["player"], e["team"]["code"]) def prettify(match): - matchdate_local = datetime.datetime.strptime(match["datetime"].replace(':', ''), "%Y-%m-%dT%H%M%S.%f%z") + matchdate_local = datetime.strptime(match["datetime"].replace(':', ''), "%Y-%m-%dT%H%M%S.%f%z") matchdate = matchdate_local - (matchdate_local.utcoffset() - datetime.timedelta(hours=2)) if match["status"] == "future": return ["Match à venir (%s) le %s : %s vs. %s" % (match["match_number"], matchdate.strftime("%A %d à %H:%M"), match["home_team"]["country"], match["away_team"]["country"])] @@ -135,7 +135,7 @@ def prettify(match): if match["status"] == "completed": msg += "Match (%s) du %s terminé : " % (match["match_number"], matchdate.strftime("%A %d à %H:%M")) else: - msg += "Match en cours (%s) depuis %d minutes : " % (match["match_number"], (datetime.datetime.now(matchdate.tzinfo) - matchdate_local).seconds / 60) + msg += "Match en cours (%s) depuis %d minutes : " % (match["match_number"], (datetime.now(matchdate.tzinfo) - matchdate_local).seconds / 60) msg += "%s %d - %d %s" % (match["home_team"]["country"], match["home_team"]["goals"], match["away_team"]["goals"], match["away_team"]["country"]) diff --git a/server/IRC.py b/server/IRC.py index 2bfe3be..d676dd9 100644 --- a/server/IRC.py +++ b/server/IRC.py @@ -16,8 +16,10 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -from datetime import datetime +import calendar +from datetime import datetime, timezone import re +import time import shlex import bot @@ -194,7 +196,7 @@ class IRCServer(SocketServer): def read(self): for line in SocketServer.read(self): - msg = IRCMessage(line, datetime.now()) + msg = IRCMessage(line, datetime.now(timezone.utc)) if msg.cmd in self.hookscmd: self.hookscmd[msg.cmd](msg) @@ -279,8 +281,7 @@ class IRCMessage: """Add an IRCv3.2 Message Tags""" # Treat special tags if key == "time": - # TODO: this is UTC timezone, nemubot works with local timezone - value = datetime.strptime(value, "%Y-%m-%dT%H:%M:%S.%fZ") + value = datetime.fromtimestamp(calendar.timegm(time.strptime(value, "%Y-%m-%dT%H:%M:%S.%fZ")), timezone.utc) # Store tag self.tags[key] = value diff --git a/tools/countdown.py b/tools/countdown.py index ed73e49..5707085 100644 --- a/tools/countdown.py +++ b/tools/countdown.py @@ -1,4 +1,4 @@ -from datetime import datetime +from datetime import datetime, timezone import time def countdown(delta, resolution=5): @@ -59,21 +59,22 @@ def countdown(delta, resolution=5): return sentence[1:] -def countdown_format(date, msg_before, msg_after, timezone=None): +def countdown_format(date, msg_before, msg_after, tz=None): """Replace in a text %s by a sentence incidated the remaining time before/after an event""" - if timezone != None: - os.environ['TZ'] = timezone + if tz != None: + oldtz = os.environ['TZ'] + os.environ['TZ'] = tz time.tzset() #Calculate time before the date - if datetime.now() > date: + if datetime.now(timezone.utc) > date: sentence_c = msg_after - delta = datetime.now() - date + delta = datetime.now(timezone.utc) - date else: sentence_c = msg_before - delta = date - datetime.now() + delta = date - datetime.now(timezone.utc) - if timezone != None: - os.environ['TZ'] = "Europe/Paris" + if tz != None: + os.environ['TZ'] = oldtz return sentence_c % countdown(delta) diff --git a/xmlparser/node.py b/xmlparser/node.py index 4a674e4..10608b5 100644 --- a/xmlparser/node.py +++ b/xmlparser/node.py @@ -1,8 +1,7 @@ # coding=utf-8 import xml.sax -from datetime import datetime -from datetime import date +from datetime import datetime, timezone import logging import sys import time @@ -67,12 +66,12 @@ class ModuleState: return source else: try: - return datetime.fromtimestamp(float(source)) + return datetime.fromtimestamp(float(source), timezone.utc) except ValueError: while True: try: return datetime.fromtimestamp(time.mktime( - time.strptime(source[:19], "%Y-%m-%d %H:%M:%S"))) + time.strptime(source[:19], "%Y-%m-%d %H:%M:%S")), timezone.utc) except ImportError: pass