Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate from pytz to zoneinfo, list (close to) all time zones #3167

Merged
merged 1 commit into from May 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 0 additions & 1 deletion anaconda.spec.in
Expand Up @@ -108,7 +108,6 @@ Requires: subscription-manager >= %{subscriptionmanagerver}
# which is apparently great for containers but unhelpful for the rest of us
Requires: cracklib-dicts

Requires: python3-pytz
Requires: teamd
%ifarch s390 s390x
Requires: openssh
Expand Down
9 changes: 4 additions & 5 deletions pyanaconda/isys/__init__.py
Expand Up @@ -28,7 +28,7 @@
import blivet.arch
import time
import datetime
import pytz
import zoneinfo

from pyanaconda.anaconda_loggers import get_module_logger
log = get_module_logger(__name__)
Expand Down Expand Up @@ -88,7 +88,7 @@ def set_system_date_time(year=None, month=None, day=None, hour=None, minute=None

"""

utc = pytz.UTC
utc = zoneinfo.ZoneInfo(key='UTC')
# If no timezone is set, use UTC
if not tz:
tz = utc
Expand All @@ -104,13 +104,12 @@ def set_system_date_time(year=None, month=None, day=None, hour=None, minute=None
minute = minute if minute is not None else now.minute
second = second if second is not None else now.second

set_date = tz.localize(datetime.datetime(year, month, day, hour, minute, second))
set_date = datetime.datetime(year, month, day, hour, minute, second, tzinfo=tz)

# Calculate the number of seconds between this time and timestamp 0
# see pytz docs, search for "Converting between timezones"
# pylint bug here: https://github.com/PyCQA/pylint/issues/1104
# pylint: disable=no-value-for-parameter
epoch = utc.localize(datetime.datetime.utcfromtimestamp(0)).astimezone(tz)
epoch = datetime.datetime.fromtimestamp(0, tz=utc).astimezone(tz)
timestamp = (set_date - epoch).total_seconds()

set_system_time(int(timestamp))
Expand Down
27 changes: 18 additions & 9 deletions pyanaconda/timezone.py
Expand Up @@ -22,9 +22,10 @@

"""

import pytz
import langtable
import zoneinfo
from collections import OrderedDict
from functools import cache

from pyanaconda.core import util
from pyanaconda.core.constants import THREAD_STORAGE
Expand All @@ -38,8 +39,7 @@
from pyanaconda.anaconda_loggers import get_module_logger
log = get_module_logger(__name__)

# The following zones are not in pytz.common_timezones and
# Etc category in pytz.all_timezones includes some more,
# The Etc category in zoneinfo.available_timezones() includes some more,
# however confusing ones (like UCT, GMT+0, GMT-0,...)
ETC_ZONES = ['GMT+1', 'GMT+2', 'GMT+3', 'GMT+4', 'GMT+5', 'GMT+6', 'GMT+7',
'GMT+8', 'GMT+9', 'GMT+10', 'GMT+11', 'GMT+12',
Expand Down Expand Up @@ -126,6 +126,18 @@ def get_preferred_timezone(territory):
return timezones[0]


@cache
def all_timezones():
"""
Get all timezones, but with the Etc zones reduced. Cached.

:rtype: set

"""
etc_zones = {"Etc/" + zone for zone in ETC_ZONES}
return zoneinfo.available_timezones() | etc_zones


def get_all_regions_and_timezones():
"""
Get a dictionary mapping the regions to the list of their timezones.
Expand All @@ -136,15 +148,14 @@ def get_all_regions_and_timezones():

result = OrderedDict()

for tz in pytz.common_timezones:
for tz in sorted(all_timezones()):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be better to move the sorting into function itself to take advantage of the cache.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically, it could. However the other function that uses this does not need sorting and it appeared to me that get_all_regions_and_timezones() is usually called just once? If it is called multiple times, should that be cached as well?

parts = tz.split("/", 1)

if len(parts) > 1:
if parts[0] not in result:
result[parts[0]] = set()
result[parts[0]].add(parts[1])

result["Etc"] = set(ETC_ZONES)
return result


Expand All @@ -157,9 +168,7 @@ def is_valid_timezone(timezone):

"""

etc_zones = ["Etc/" + zone for zone in ETC_ZONES]

return timezone in pytz.common_timezones + etc_zones
return timezone in all_timezones()


def get_timezone(timezone):
Expand All @@ -170,4 +179,4 @@ def get_timezone(timezone):
:rtype: datetime.tzinfo
"""

return pytz.timezone(timezone)
return zoneinfo.ZoneInfo(timezone)