diff options
author | 2021-04-13 19:05:45 +0200 | |
---|---|---|
committer | 2021-04-13 22:28:21 +0200 | |
commit | 9ab05cbe3f23d442b5bc73311e0c3e8b075e396e (patch) | |
tree | df685646963ed329af23c56f477c332cf2df8a7e | |
parent | Merge pull request #1521 from ToxicKidz/dont-use-startswith (diff) |
Branding: use tz-aware datetime representation
Using `datetime.utcnow` produces a tz-naive object. When converting
the object into a POSIX timestamp (L212), the library then converts
the naive object into UTC, which will offset it unless the local
timezone is UTC. We prevent this behaviour by using an Arrow repr
instead, which is by default tz-aware. Since the object already
knows it is in UTC, it does not shift when converting to a timestamp.
Because L233 used `fromtimestamp` rather than `utcfromtimestamp`,
the timestamp then got converted back into local time, canceling
the previous error. Therefore, the bug wasn't observable from logs,
as the times looked correct, but were being stored incorrectly.
By using `Arrow.utcfromtimestamp`, the created object will be aware
of being UTC again, which is more safe.
-rw-r--r-- | bot/exts/backend/branding/_cog.py | 15 |
1 files changed, 8 insertions, 7 deletions
diff --git a/bot/exts/backend/branding/_cog.py b/bot/exts/backend/branding/_cog.py index 0a4ddcc88..fdc4a4167 100644 --- a/bot/exts/backend/branding/_cog.py +++ b/bot/exts/backend/branding/_cog.py @@ -3,12 +3,13 @@ import contextlib import logging import random import typing as t -from datetime import datetime, time, timedelta +from datetime import timedelta from enum import Enum from operator import attrgetter import async_timeout import discord +from arrow import Arrow from async_rediscache import RedisCache from discord.ext import commands, tasks @@ -208,7 +209,7 @@ class Branding(commands.Cog): if success: await self.cache_icons.increment(next_icon) # Push the icon into the next iteration. - timestamp = datetime.utcnow().timestamp() + timestamp = Arrow.utcnow().timestamp() await self.cache_information.set("last_rotation_timestamp", timestamp) return success @@ -229,8 +230,8 @@ class Branding(commands.Cog): await self.rotate_icons() return - last_rotation = datetime.fromtimestamp(last_rotation_timestamp) - difference = (datetime.utcnow() - last_rotation) + timedelta(minutes=5) + last_rotation = Arrow.utcfromtimestamp(last_rotation_timestamp) + difference = (Arrow.utcnow() - last_rotation) + timedelta(minutes=5) log.trace(f"Icons last rotated at {last_rotation} (difference: {difference}).") @@ -485,11 +486,11 @@ class Branding(commands.Cog): await self.daemon_loop() log.trace("Daemon before: calculating time to sleep before loop begins.") - now = datetime.utcnow() + now = Arrow.utcnow() # The actual midnight moment is offset into the future to prevent issues with imprecise sleep. - tomorrow = now + timedelta(days=1) - midnight = datetime.combine(tomorrow, time(minute=1)) + tomorrow = now.shift(days=1) + midnight = tomorrow.replace(hour=0, minute=1, second=0, microsecond=0) sleep_secs = (midnight - now).total_seconds() log.trace(f"Daemon before: sleeping {sleep_secs} seconds before next-up midnight: {midnight}.") |