python/cpython · error · ValueError
timezone changed during initialization
Error message
timezone changed during initialization
What it means
Raised by _strptime.LocaleTime.__init__ after it finishes computing cached locale tables (weekday/month names, AM/PM, timezone data). At the end it re-reads time.tzname and time.daylight and compares them to the values captured at the start; if they differ, the cached tables would be inconsistent, so a ValueError is raised. It is a concurrency/environment-consistency guard, not a user-input error.
Source
Thrown at Lib/_strptime.py:117
running. The check here is done in case someone does not think about
doing this.
Only other possible issue is if someone changed the timezone and did
not call tz.tzset . That is an issue for the programmer, though,
since changing the timezone is worthless without that call.
"""
self.lang = _getlang()
self.__calc_weekday()
self.__calc_month()
self.__calc_am_pm()
self.__calc_alt_digits()
self.__calc_timezone()
self.__calc_date_time()
if _getlang() != self.lang:
raise ValueError("locale changed during initialization")
if time.tzname != self.tzname or time.daylight != self.daylight:
raise ValueError("timezone changed during initialization")
def __calc_weekday(self):
# Set self.a_weekday and self.f_weekday using the calendar
# module.
a_weekday = [calendar.day_abbr[i].lower() for i in range(7)]
f_weekday = [calendar.day_name[i].lower() for i in range(7)]
self.a_weekday = a_weekday
self.f_weekday = f_weekday
def __calc_month(self):
# Set self.f_month and self.a_month using the calendar module.
a_month = [calendar.month_abbr[i].lower() for i in range(13)]
f_month = [calendar.month_name[i].lower() for i in range(13)]
self.a_month = a_month
self.f_month = f_month
def __calc_am_pm(self):
# Set self.am_pm by using time.strftime().View on GitHub (pinned to bc6749cc3b)
Solutions
- Set the TZ environment variable and call time.tzset() once at process startup, before spawning worker threads that call strptime
- Retry the strptime() call once in an except ValueError block to let the cache rebuild consistently
- Serialize TZ/locale changes and strptime use behind a lock
- Pass explicit tz-aware parsing (e.g. fromisoformat or dateutil) instead of relying on the process timezone
Example fix
# before os.environ['TZ'] = 'UTC' # racing with strptime in other threads time.tzset() # after os.environ['TZ'] = 'UTC' time.tzset() # do once at startup, before threads start parsing
Defensive patterns
Strategy: retry
Validate before calling
def safe_strptime(s, fmt, retries=2):
for i in range(retries + 1):
try:
return _strptime_time(s, fmt)
except ValueError as e:
if 'changed during initialization' in str(e) and i < retries:
continue
raise Try / catch
try:
t = time.strptime(data, fmt)
except ValueError as e:
if 'changed during initialization' in str(e):
t = time.strptime(data, fmt) # cache rebuilt consistently on 2nd call
else:
raise Prevention
- Set TZ and call time.tzset() once at startup before threads begin parsing
- Never mutate os.environ['TZ'] from worker threads while parsing is in flight
- Pin parsing to explicit offsets (%z) instead of the process timezone
When it happens
Trigger: Another thread calls time.tzset() (or sets os.environ['TZ'] followed by tzset) while a strptime() call is rebuilding the _TimeRE_cache (e.g. first strptime call after locale/TZ change, or after cache invalidation because _getlang()/time.tzname/time.daylight no longer match the cache).
Common situations: Multithreaded servers or test suites where one thread changes the TZ environment variable or locale while other threads parse datetime strings with time.strptime or datetime.datetime.strptime; rare race on first use after a TZ change.
Related errors
- locale changed during initialization
- Missing colon in %:z before '{rest}', got '{data_string}'
- Inconsistent use of : in {found_dict[group_key]}
- Day of month directive '%d' may not be used without a year d
- strptime() argument {} must be str, not {}
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/9b2ea74e4461e5db.
Report an issue: GitHub.