diff --git a/docs/install.rst b/docs/install.rst index eb618035..fa06068a 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -64,7 +64,7 @@ automatically installed without any action on your part: * `pygments `_, for syntax highlighting * `docutils `_, for supporting reStructuredText as an input format -* `pytz `_, for timezone definitions +* `backports.zoneinfo` `_, for timezone definitions * `blinker `_, an object-to-object and broadcast signaling system * `unidecode `_, for ASCII diff --git a/pelican/contents.py b/pelican/contents.py index 1740df88..84ee8c3e 100644 --- a/pelican/contents.py +++ b/pelican/contents.py @@ -7,7 +7,10 @@ import re from html import unescape from urllib.parse import unquote, urljoin, urlparse, urlunparse -import pytz +try: + import zoneinfo +except ImportError: + from backports import zoneinfo from pelican.plugins import signals from pelican.settings import DEFAULT_CONFIG @@ -122,7 +125,7 @@ class Content: # manage timezone default_timezone = settings.get('TIMEZONE', 'UTC') timezone = getattr(self, 'timezone', default_timezone) - self.timezone = pytz.timezone(timezone) + self.timezone = zoneinfo.ZoneInfo(timezone) if hasattr(self, 'date'): self.date = set_date_tzinfo(self.date, timezone) @@ -525,7 +528,7 @@ class Article(Content): if self.date.tzinfo is None: now = datetime.datetime.now() else: - now = datetime.datetime.utcnow().replace(tzinfo=pytz.utc) + now = datetime.datetime.utcnow().replace(tzinfo=zoneinfo.ZoneInfo("UTC")) if self.date > now: self.status = 'draft' diff --git a/pelican/tests/test_utils.py b/pelican/tests/test_utils.py index 710e14ed..3fc06aa0 100644 --- a/pelican/tests/test_utils.py +++ b/pelican/tests/test_utils.py @@ -6,7 +6,10 @@ import time from sys import platform from tempfile import mkdtemp -import pytz +try: + import zoneinfo +except ImportError: + from backports import zoneinfo from pelican import utils from pelican.generators import TemplatePagesGenerator @@ -42,21 +45,21 @@ class TestUtils(LoggedTestCase): year=2012, month=11, day=22, hour=22, minute=11) date_hour_z = utils.SafeDatetime( year=2012, month=11, day=22, hour=22, minute=11, - tzinfo=pytz.timezone('UTC')) + tzinfo=zoneinfo.ZoneInfo('UTC')) date_hour_est = utils.SafeDatetime( year=2012, month=11, day=22, hour=22, minute=11, - tzinfo=pytz.timezone('EST')) + tzinfo=zoneinfo.ZoneInfo('EST')) date_hour_sec = utils.SafeDatetime( year=2012, month=11, day=22, hour=22, minute=11, second=10) date_hour_sec_z = utils.SafeDatetime( year=2012, month=11, day=22, hour=22, minute=11, second=10, - tzinfo=pytz.timezone('UTC')) + tzinfo=zoneinfo.ZoneInfo('UTC')) date_hour_sec_est = utils.SafeDatetime( year=2012, month=11, day=22, hour=22, minute=11, second=10, - tzinfo=pytz.timezone('EST')) + tzinfo=zoneinfo.ZoneInfo('EST')) date_hour_sec_frac_z = utils.SafeDatetime( year=2012, month=11, day=22, hour=22, minute=11, second=10, - microsecond=123000, tzinfo=pytz.timezone('UTC')) + microsecond=123000, tzinfo=zoneinfo.ZoneInfo('UTC')) dates = { '2012-11-22': date, '2012/11/22': date, @@ -78,13 +81,13 @@ class TestUtils(LoggedTestCase): iso_8601_date = utils.SafeDatetime(year=1997, month=7, day=16) iso_8601_date_hour_tz = utils.SafeDatetime( year=1997, month=7, day=16, hour=19, minute=20, - tzinfo=pytz.timezone('CET')) + tzinfo=zoneinfo.ZoneInfo('CET')) iso_8601_date_hour_sec_tz = utils.SafeDatetime( year=1997, month=7, day=16, hour=19, minute=20, second=30, - tzinfo=pytz.timezone('CET')) + tzinfo=zoneinfo.ZoneInfo('CET')) iso_8601_date_hour_sec_ms_tz = utils.SafeDatetime( year=1997, month=7, day=16, hour=19, minute=20, second=30, - microsecond=450000, tzinfo=pytz.timezone('CET')) + microsecond=450000, tzinfo=zoneinfo.ZoneInfo('CET')) iso_8601 = { '1997-07-16': iso_8601_date, '1997-07-16T19:20+01:00': iso_8601_date_hour_tz, diff --git a/pelican/tools/pelican_quickstart.py b/pelican/tools/pelican_quickstart.py index 2d5629ef..eab1d30f 100755 --- a/pelican/tools/pelican_quickstart.py +++ b/pelican/tools/pelican_quickstart.py @@ -4,10 +4,14 @@ import argparse import locale import os from typing import Mapping +from zoneinfo import available_timezones from jinja2 import Environment, FileSystemLoader -import pytz +try: + import zoneinfo +except ImportError: + from backports import zoneinfo try: import readline # NOQA @@ -158,12 +162,13 @@ def ask(question, answer=str, default=None, length=None): def ask_timezone(question, default, tzurl): """Prompt for time zone and validate input""" - lower_tz = [tz.lower() for tz in pytz.all_timezones] + available_timezones = list(zoneinfo.available_timezones()) + lower_tz = [tz.lower() for tz in available_timezones] while True: r = ask(question, str, default) r = r.strip().replace(' ', '_').lower() if r in lower_tz: - r = pytz.all_timezones[lower_tz.index(r)] + r = available_timezones[lower_tz.index(r)] break else: print('Please enter a valid time zone:\n' diff --git a/pelican/utils.py b/pelican/utils.py index 17667078..0b474f4e 100644 --- a/pelican/utils.py +++ b/pelican/utils.py @@ -20,7 +20,10 @@ import dateutil.parser from markupsafe import Markup -import pytz +try: + import zoneinfo +except ImportError: + from backports import zoneinfo logger = logging.getLogger(__name__) @@ -920,8 +923,8 @@ class FileSystemWatcher: def set_date_tzinfo(d, tz_name=None): """Set the timezone for dates that don't have tzinfo""" if tz_name and not d.tzinfo: - tz = pytz.timezone(tz_name) - d = tz.localize(d) + tz = zoneinfo.ZoneInfo(tz_name) + d = d.replace(tzinfo=tz) return SafeDatetime(d.year, d.month, d.day, d.hour, d.minute, d.second, d.microsecond, d.tzinfo) return d diff --git a/pyproject.toml b/pyproject.toml index 8d7749b0..5ab037ef 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,10 +37,10 @@ feedgenerator = ">=1.9" jinja2 = ">=2.7" pygments = ">=2.6" python-dateutil = ">=2.8" -pytz = ">=2020.1" rich = ">=10.1" unidecode = ">=1.1" markdown = {version = ">=3.1", optional = true} +"backports.zoneinfo" = "^0.2.1" [tool.poetry.dev-dependencies] BeautifulSoup4 = "^4.9" diff --git a/setup.py b/setup.py index 3b538992..27414a97 100755 --- a/setup.py +++ b/setup.py @@ -5,12 +5,11 @@ from os.path import join, relpath from setuptools import find_packages, setup - version = "4.7.1" requires = ['feedgenerator >= 1.9', 'jinja2 >= 2.7', 'pygments', - 'docutils>=0.15', 'pytz >= 0a', 'blinker', 'unidecode', - 'python-dateutil', 'rich'] + 'docutils>=0.15', 'backports.zoneinfo;python_version<"3.9"', + 'blinker', 'unidecode', 'python-dateutil', 'rich'] entry_points = { 'console_scripts': [