diff --git a/agent/tools/scheduler/time_utils.py b/agent/tools/scheduler/time_utils.py index 0b27be7c..7f1c7bdc 100644 --- a/agent/tools/scheduler/time_utils.py +++ b/agent/tools/scheduler/time_utils.py @@ -7,7 +7,16 @@ naive local-time behaviour so existing stored tasks are not reinterpreted. """ from croniter import croniter from datetime import datetime, timedelta, timezone -from zoneinfo import ZoneInfo + +# zoneinfo joined the standard library in Python 3.9. Without it, only named +# IANA timezones are unavailable; legacy naive-local tasks keep working. +try: + from zoneinfo import ZoneInfo +except ImportError: + try: + from backports.zoneinfo import ZoneInfo + except ImportError: + ZoneInfo = None UTC = timezone.utc @@ -38,6 +47,10 @@ def resolve_timezone(name=None): return datetime.now().astimezone().tzinfo if not isinstance(name, str) or not name.strip(): raise ValueError("timezone must be a non-empty IANA name") + if ZoneInfo is None: + raise ValueError( + "IANA timezones require Python 3.9+ or the backports.zoneinfo package" + ) return ZoneInfo(name.strip()) diff --git a/desktop/build/requirements-desktop.txt b/desktop/build/requirements-desktop.txt index 14826d45..d6c9907e 100644 --- a/desktop/build/requirements-desktop.txt +++ b/desktop/build/requirements-desktop.txt @@ -28,6 +28,9 @@ Pillow python-dotenv>=1.0.0 PyYAML>=6.0 croniter>=2.0.0 +# zoneinfo is stdlib from 3.9 (the Win7 build runs 3.8); Windows has no system tz database +backports.zoneinfo; python_version < "3.9" +tzdata; sys_platform == "win32" click>=8.0 qrcode json-repair diff --git a/requirements.txt b/requirements.txt index ec5af851..40ecfe1a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,6 +11,9 @@ Pillow python-dotenv>=1.0.0 PyYAML>=6.0 croniter>=2.0.0 +# zoneinfo is stdlib from 3.9; Windows has no system tz database +backports.zoneinfo; python_version < "3.9" +tzdata; sys_platform == "win32" click>=8.0 qrcode json-repair