Upgrade to 4.0 causes ZoneInfoNotFoundError
See original GitHub issueSummary
Our project uses dateparses, which again depends on tzlocal
. After auto-upgrading our packages, and therunder tzlocal from 3.0 to 4.0 our build started failing. Its either that or related to your dependency pytz-deprecation-shim
.
When i pinned our build to tzlocal = 3.0, the problem went away.
Details
- tzlocal version = 4.0
- Docker image: python:3.9.6-buster
Other things:
- We use poetry lock
Our code
def any_to_datetime(s: str) -> datetime:
# Hack around that '9999-12-31T23:59:59' crashes when parsed
if s[:4] == "9999":
d = datetime(9999, 12, 31, 23, 59, 59)
return ensure_timezoned(d)
if parsed_datetime := dateparser.parse(s): # <- Line 18, raises tzlocal.utils.ZoneInfoNotFoundError
return ensure_timezoned(parsed_datetime)
raise Exception(f"Could not parse {s=}")
Exception
../api_import/utils/date.py:18: in any_to_datetime
if parsed_datetime := dateparser.parse(s):
/usr/local/lib/python3.9/site-packages/dateparser/conf.py:92: in wrapper
return f(*args, **kwargs)
/usr/local/lib/python3.9/site-packages/dateparser/__init__.py:61: in parse
data = parser.get_date_data(date_string, date_formats)
/usr/local/lib/python3.9/site-packages/dateparser/date.py:428: in get_date_data
parsed_date = _DateLocaleParser.parse(
/usr/local/lib/python3.9/site-packages/dateparser/date.py:178: in parse
return instance._parse()
/usr/local/lib/python3.9/site-packages/dateparser/date.py:182: in _parse
date_data = self._parsers[parser_name]()
/usr/local/lib/python3.9/site-packages/dateparser/date.py:196: in _try_freshness_parser
return freshness_date_parser.get_date_data(self._get_translated_date(), self._settings)
/usr/local/lib/python3.9/site-packages/dateparser/freshness_date_parser.py:156: in get_date_data
date, period = self.parse(date_string, settings)
/usr/local/lib/python3.9/site-packages/dateparser/freshness_date_parser.py:93: in parse
now = datetime.now(self.get_local_tz())
/usr/local/lib/python3.9/site-packages/dateparser/freshness_date_parser.py:41: in get_local_tz
return get_localzone()
/usr/local/lib/python3.9/site-packages/tzlocal/unix.py:205: in get_localzone
_cache_tz = _get_localzone()
/usr/local/lib/python3.9/site-packages/tzlocal/unix.py:167: in _get_localzone
tzname = _get_localzone_name(_root)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
_root = '/'
def _get_localzone_name(_root="/"):
"""Tries to find the local timezone configuration.
This method finds the timezone name, if it can, or it returns None.
The parameter _root makes the function look for files like /etc/localtime
beneath the _root directory. This is primarily used by the tests.
In normal usage you call the function without parameters."""
# First try the ENV setting.
tzenv = utils._tz_name_from_env()
if tzenv:
return tzenv
# Are we under Termux on Android?
if os.path.exists(os.path.join(_root, "system/bin/getprop")):
import subprocess
androidtz = (
subprocess.check_output(["getprop", "persist.sys.timezone"])
.strip()
.decode()
)
return androidtz
# Now look for distribution specific configuration files
# that contain the timezone name.
# Stick all of them in a dict, to compare later.
found_configs = {}
for configfile in ("etc/timezone", "var/db/zoneinfo"):
tzpath = os.path.join(_root, configfile)
try:
with open(tzpath, "rt") as tzfile:
data = tzfile.read()
etctz = data.strip()
if not etctz:
# Empty file, skip
continue
for etctz in data.splitlines():
# Get rid of host definitions and comments:
if " " in etctz:
etctz, dummy = etctz.split(" ", 1)
if "#" in etctz:
etctz, dummy = etctz.split("#", 1)
if not etctz:
continue
found_configs[tzpath] = etctz.replace(" ", "_")
except (IOError, UnicodeDecodeError):
# File doesn't exist or is a directory, or it's a binary file.
continue
# CentOS has a ZONE setting in /etc/sysconfig/clock,
# OpenSUSE has a TIMEZONE setting in /etc/sysconfig/clock and
# Gentoo has a TIMEZONE setting in /etc/conf.d/clock
# We look through these files for a timezone:
zone_re = re.compile(r"\s*ZONE\s*=\s*\"")
timezone_re = re.compile(r"\s*TIMEZONE\s*=\s*\"")
end_re = re.compile('"')
for filename in ("etc/sysconfig/clock", "etc/conf.d/clock"):
tzpath = os.path.join(_root, filename)
try:
with open(tzpath, "rt") as tzfile:
data = tzfile.readlines()
for line in data:
# Look for the ZONE= setting.
match = zone_re.match(line)
if match is None:
# No ZONE= setting. Look for the TIMEZONE= setting.
match = timezone_re.match(line)
if match is not None:
# Some setting existed
line = line[match.end():]
etctz = line[: end_re.search(line).start()]
# We found a timezone
found_configs[tzpath] = etctz.replace(" ", "_")
except (IOError, UnicodeDecodeError):
# UnicodeDecode handles when clock is symlink to /etc/localtime
continue
# systemd distributions use symlinks that include the zone name,
# see manpage of localtime(5) and timedatectl(1)
tzpath = os.path.join(_root, "etc/localtime")
if os.path.exists(tzpath) and os.path.islink(tzpath):
etctz = tzpath = os.path.realpath(tzpath)
start = etctz.find("/") + 1
while start != 0:
etctz = etctz[start:]
try:
pds.timezone(etctz)
found_configs[tzpath] = etctz.replace(" ", "_")
except pds.UnknownTimeZoneError:
pass
start = etctz.find("/") + 1
if len(found_configs) > 0:
# We found some explicit config of some sort!
if len(found_configs) > 1:
# Uh-oh, multiple configs. See if they match:
unique_tzs = set()
for tzname in found_configs.values():
# Get rid of any Etc's
tzname = tzname.replace("Etc/", "")
# In practice these are the same:
tzname = tzname.replace("UTC", "GMT")
# Let's handle these synonyms as well. Many systems have tons
# of synonyms, including country names and "Zulu" and other
# nonsense. Those will be seen as different ones. Let's stick
# to the official zoneinfo Continent/City names.
if tzname in ["GMT0", "GMT+0", "GMT-0"]:
tzname = "GMT"
unique_tzs.add(tzname)
if len(unique_tzs) != 1:
message = "Multiple conflicting time zone configurations found:\n"
for key, value in found_configs.items():
message += f"{key}: {value}\n"
message += "Fix the configuration, or set the time zone in a TZ environment variable.\n"
> raise utils.ZoneInfoNotFoundError(message)
E tzlocal.utils.ZoneInfoNotFoundError: 'Multiple conflicting time zone configurations found:\n/etc/timezone: Etc/UTC\n/usr/share/zoneinfo/UCT: UCT\nFix the configuration, or set the time zone in a TZ environment variable.\n'
/usr/local/lib/python3.9/site-packages/tzlocal/unix.py:146: ZoneInfoNotFoundError
Issue Analytics
- State:
- Created 2 years ago
- Reactions:2
- Comments:11 (6 by maintainers)
Top Results From Across the Web
Django 4 Error: 'No time zone found with key ...'
After upgrades pytz and tzdata my Django project is working just fine again! ... test django in 4.0.5 and 4.1 will working: my...
Read more >Time zones - Django documentation
The main reason is daylight saving time (DST). ... Changed in Django 4.0: ... Use them to build the time zone selection logic...
Read more >[Django] #33674: Timezones cause 500 errors to not email the ...
and the users are no longer sent to my 500 page. Here's some information: * debug=True causes things to work correctly (no email...
Read more >What is the zoneinfo.ZoneInfoNotFoundError in Python?
It is raised by the ZoneInfo class constructor if no matching file is found on the search path. Possible reasons for errors: System...
Read more >zoneinfo — IANA time zone support — Python 3.11.1 ...
... recommended to declare a dependency on tzdata. If neither system data nor tzdata are available, all calls to ZoneInfo will raise ZoneInfoNotFoundError...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
OK, I released 4.0.1.
I released a 4.0.1b1 with this fix, see if that fixes it.