From 1e0b397720899ca1663038de08e3c6bd3d62edc2 Mon Sep 17 00:00:00 2001 From: William Chu Date: Wed, 14 Feb 2024 17:39:09 +1100 Subject: [PATCH 1/2] fix(timestamps): generate timestamps correctly and remove the deprecated pytz --- backend/bot/scheduler/scheduler.py | 4 +-- backend/bot/shared/tools.py | 17 ++++++++---- backend/requirements.txt | 1 - backend/tests/test_tools.py | 44 ++++++++++++++++++++++++++++++ 4 files changed, 57 insertions(+), 9 deletions(-) create mode 100644 backend/tests/test_tools.py diff --git a/backend/bot/scheduler/scheduler.py b/backend/bot/scheduler/scheduler.py index 4d8133f0..3fcbba1c 100644 --- a/backend/bot/scheduler/scheduler.py +++ b/backend/bot/scheduler/scheduler.py @@ -1,3 +1,4 @@ +import zoneinfo import config import datetime import slack_sdk @@ -14,7 +15,6 @@ store_slack_user_list_db, ) from iblog import logger -from pytz import timezone from typing import List @@ -26,7 +26,7 @@ class TaskScheduler: def __init__(self): self.scheduler = BackgroundScheduler( jobstores=jobstores, - timezone=timezone(application_timezone), + timezone=zoneinfo.ZoneInfo(application_timezone), ) def list_jobs(self) -> List[Job]: diff --git a/backend/bot/shared/tools.py b/backend/bot/shared/tools.py index 2f3dad9b..027fac33 100644 --- a/backend/bot/shared/tools.py +++ b/backend/bot/shared/tools.py @@ -1,4 +1,5 @@ import config +import zoneinfo import ipaddress import itertools import random @@ -6,7 +7,6 @@ from datetime import datetime from iblog import logger -from pytz import timezone from typing import Any, List @@ -19,18 +19,23 @@ application_timezone = config.active.options.get("timezone") -def fetch_timestamp(short: bool = False): +def fetch_timestamp(short: bool = False, timezone: str | None = None) -> str: """Return a localized, formatted timestamp using datetime.now()""" - now = datetime.now() - localized = timezone(application_timezone).localize(now) + localized = datetime.now( + zoneinfo.ZoneInfo(timezone or application_timezone) + ) if short: return localized.strftime(timestamp_fmt_short) return localized.strftime(timestamp_fmt) -def fetch_timestamp_from_time_obj(t: datetime): +def fetch_timestamp_from_time_obj( + t: datetime, timezone: str | None = None +) -> str: """Return a localized, formatted timestamp using datetime.datetime class""" - return timezone(application_timezone).localize(t).strftime(timestamp_fmt) + return t.astimezone( + zoneinfo.ZoneInfo(timezone or application_timezone) + ).strftime(timestamp_fmt) def find_index_in_list(lst: List, key: Any, value: Any): diff --git a/backend/requirements.txt b/backend/requirements.txt index c57fdc2b..b7a24e1a 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -22,7 +22,6 @@ pytest-mock==3.14.0 pytest-sqlalchemy-mock==0.1.5 python-dotenv==1.0.1 python-json-logger==2.0.7 -pytz==2024.1 PyYAML==6.0.1 requests==2.31.0 requests-mock==1.11.0 diff --git a/backend/tests/test_tools.py b/backend/tests/test_tools.py new file mode 100644 index 00000000..fe93f1f6 --- /dev/null +++ b/backend/tests/test_tools.py @@ -0,0 +1,44 @@ +import datetime + +from bot.shared.tools import ( + fetch_timestamp, + fetch_timestamp_from_time_obj, + timestamp_fmt, + timestamp_fmt_short, +) + + +class TestTimeHelpers: + def test_fetch_timestamp_generates_the_correct_timestamp(self): + utc_timestamp = fetch_timestamp(timezone="UTC") + melbourne_timestamp = fetch_timestamp(timezone="Australia/Melbourne") + + parsed_melbourne = datetime.datetime.strptime( + utc_timestamp[:13], "%Y-%m-%dT%H" + ) + parsed_utc = datetime.datetime.strptime( + melbourne_timestamp[:13], "%Y-%m-%dT%H" + ) + + assert ( + parsed_melbourne.hour != parsed_utc.hour + ), "The timestamps should have different hours when using differnt timezones" + + def test_fetch_timestamp_short(self): + short_timestamp = fetch_timestamp(short=True, timezone="UTC") + + assert datetime.datetime.strptime( + short_timestamp, timestamp_fmt_short + ), "Should be able to reparse the short format" + + def test_fetch_timestamp_from_time_obj(self): + now = datetime.datetime.now(datetime.UTC) + + now_as_est = fetch_timestamp_from_time_obj( + now, timezone="Australia/Melbourne" + ) + + now_as_melbourne_datetime = datetime.datetime.strptime( + now_as_est, timestamp_fmt + ) + assert now_as_melbourne_datetime.hour != now.hour From 9417613a333dced9fe2a6c341f1b678a596f29e5 Mon Sep 17 00:00:00 2001 From: William Chu Date: Fri, 24 May 2024 09:33:50 +1000 Subject: [PATCH 2/2] chore: bump version to v1.10.8 --- backend/config.py | 2 +- deploy/charts/incident-bot/Chart.yaml | 4 ++-- .../incident-bot/overlays/production/kustomization.yaml | 2 +- docs/deploy/overlays/production/kustomization.yaml | 2 +- version | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/backend/config.py b/backend/config.py index 8a8f22c2..024f2a30 100644 --- a/backend/config.py +++ b/backend/config.py @@ -9,7 +9,7 @@ from iblog import logger, log_level from typing import Dict, List -__version__ = "v1.10.7" +__version__ = "v1.10.8" # .env parse dotenv_path = os.path.join(os.path.dirname(__file__), ".env") diff --git a/deploy/charts/incident-bot/Chart.yaml b/deploy/charts/incident-bot/Chart.yaml index 80534193..62a77f27 100644 --- a/deploy/charts/incident-bot/Chart.yaml +++ b/deploy/charts/incident-bot/Chart.yaml @@ -17,10 +17,10 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 1.10.7 +version: 1.10.8 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: '1.10.7' +appVersion: '1.10.8' diff --git a/deploy/kustomize/incident-bot/overlays/production/kustomization.yaml b/deploy/kustomize/incident-bot/overlays/production/kustomization.yaml index 31093fb5..a10d8595 100755 --- a/deploy/kustomize/incident-bot/overlays/production/kustomization.yaml +++ b/deploy/kustomize/incident-bot/overlays/production/kustomization.yaml @@ -7,7 +7,7 @@ bases: images: - name: eb129/incident-bot - newTag: v1.10.7 + newTag: v1.10.8 configMapGenerator: - name: incident-bot-config diff --git a/docs/deploy/overlays/production/kustomization.yaml b/docs/deploy/overlays/production/kustomization.yaml index 6bca9dec..d64cec99 100755 --- a/docs/deploy/overlays/production/kustomization.yaml +++ b/docs/deploy/overlays/production/kustomization.yaml @@ -7,7 +7,7 @@ bases: images: - name: eb129/incident-bot-docs - newTag: v1.10.7 + newTag: v1.10.8 generatorOptions: disableNameSuffixHash: true diff --git a/version b/version index a4e5ba80..7e84580d 100644 --- a/version +++ b/version @@ -1 +1 @@ -v1.10.7 +v1.10.8