about summary refs log tree commit diff
path: root/.venv/lib/python3.12/site-packages/tzlocal/win32.py
diff options
context:
space:
mode:
authorS. Solomon Darnell2025-03-28 21:52:21 -0500
committerS. Solomon Darnell2025-03-28 21:52:21 -0500
commit4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch)
treeee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/tzlocal/win32.py
parentcc961e04ba734dd72309fb548a2f97d67d578813 (diff)
downloadgn-ai-master.tar.gz
two version of R2R are here HEAD master
Diffstat (limited to '.venv/lib/python3.12/site-packages/tzlocal/win32.py')
-rw-r--r--.venv/lib/python3.12/site-packages/tzlocal/win32.py144
1 files changed, 144 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/tzlocal/win32.py b/.venv/lib/python3.12/site-packages/tzlocal/win32.py
new file mode 100644
index 00000000..cfcdba53
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/tzlocal/win32.py
@@ -0,0 +1,144 @@
+import logging
+from datetime import datetime
+
+try:
+    import _winreg as winreg
+except ImportError:
+    import winreg
+
+import zoneinfo
+
+from tzlocal import utils
+from tzlocal.windows_tz import win_tz
+
+_cache_tz = None
+_cache_tz_name = None
+
+log = logging.getLogger("tzlocal")
+
+
+def valuestodict(key):
+    """Convert a registry key's values to a dictionary."""
+    result = {}
+    size = winreg.QueryInfoKey(key)[1]
+    for i in range(size):
+        data = winreg.EnumValue(key, i)
+        result[data[0]] = data[1]
+    return result
+
+
+def _get_dst_info(tz):
+    # Find the offset for when it doesn't have DST:
+    dst_offset = std_offset = None
+    has_dst = False
+    year = datetime.now().year
+    for dt in (datetime(year, 1, 1), datetime(year, 6, 1)):
+        if tz.dst(dt).total_seconds() == 0.0:
+            # OK, no DST during winter, get this offset
+            std_offset = tz.utcoffset(dt).total_seconds()
+        else:
+            has_dst = True
+
+    return has_dst, std_offset, dst_offset
+
+
+def _get_localzone_name():
+    # Windows is special. It has unique time zone names (in several
+    # meanings of the word) available, but unfortunately, they can be
+    # translated to the language of the operating system, so we need to
+    # do a backwards lookup, by going through all time zones and see which
+    # one matches.
+    tzenv = utils._tz_name_from_env()
+    if tzenv:
+        return tzenv
+
+    log.debug("Looking up time zone info from registry")
+    handle = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE)
+
+    TZLOCALKEYNAME = r"SYSTEM\CurrentControlSet\Control\TimeZoneInformation"
+    localtz = winreg.OpenKey(handle, TZLOCALKEYNAME)
+    keyvalues = valuestodict(localtz)
+    localtz.Close()
+
+    if "TimeZoneKeyName" in keyvalues:
+        # Windows 7 and later
+
+        # For some reason this returns a string with loads of NUL bytes at
+        # least on some systems. I don't know if this is a bug somewhere, I
+        # just work around it.
+        tzkeyname = keyvalues["TimeZoneKeyName"].split("\x00", 1)[0]
+    else:
+        # Don't support XP any longer
+        raise LookupError("Can not find Windows timezone configuration")
+
+    timezone = win_tz.get(tzkeyname)
+    if timezone is None:
+        # Nope, that didn't work. Try adding "Standard Time",
+        # it seems to work a lot of times:
+        timezone = win_tz.get(tzkeyname + " Standard Time")
+
+    # Return what we have.
+    if timezone is None:
+        raise zoneinfo.ZoneInfoNotFoundError(tzkeyname)
+
+    if keyvalues.get("DynamicDaylightTimeDisabled", 0) == 1:
+        # DST is disabled, so don't return the timezone name,
+        # instead return Etc/GMT+offset
+
+        tz = zoneinfo.ZoneInfo(timezone)
+        has_dst, std_offset, dst_offset = _get_dst_info(tz)
+        if not has_dst:
+            # The DST is turned off in the windows configuration,
+            # but this timezone doesn't have DST so it doesn't matter
+            return timezone
+
+        if std_offset is None:
+            raise zoneinfo.ZoneInfoNotFoundError(
+                f"{tzkeyname} claims to not have a non-DST time!?"
+            )
+
+        if std_offset % 3600:
+            # I can't convert this to an hourly offset
+            raise zoneinfo.ZoneInfoNotFoundError(
+                f"tzlocal can't support disabling DST in the {timezone} zone."
+            )
+
+        # This has whole hours as offset, return it as Etc/GMT
+        return f"Etc/GMT{-std_offset//3600:+.0f}"
+
+    return timezone
+
+
+def get_localzone_name() -> str:
+    """Get the zoneinfo timezone name that matches the Windows-configured timezone."""
+    global _cache_tz_name
+    if _cache_tz_name is None:
+        _cache_tz_name = _get_localzone_name()
+
+    return _cache_tz_name
+
+
+def get_localzone() -> zoneinfo.ZoneInfo:
+    """Returns the zoneinfo-based tzinfo object that matches the Windows-configured timezone."""
+
+    global _cache_tz
+    if _cache_tz is None:
+        _cache_tz = zoneinfo.ZoneInfo(get_localzone_name())
+
+    if not utils._tz_name_from_env():
+        # If the timezone does NOT come from a TZ environment variable,
+        # verify that it's correct. If it's from the environment,
+        # we accept it, this is so you can run tests with different timezones.
+        utils.assert_tz_offset(_cache_tz, error=False)
+
+    return _cache_tz
+
+
+def reload_localzone() -> zoneinfo.ZoneInfo:
+    """Reload the cached localzone. You need to call this if the timezone has changed."""
+    global _cache_tz
+    global _cache_tz_name
+    _cache_tz_name = _get_localzone_name()
+    _cache_tz = zoneinfo.ZoneInfo(_cache_tz_name)
+    utils.assert_tz_offset(_cache_tz, error=False)
+    return _cache_tz