prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Clock and tzupdate 
  ### The issue:
  
  qtile version:
  0.21.0
  
  These days I need to travel with my system and have the need to update my timezone in order to work with my calendar. I'm using `tzupdate` which easily updates my timezone with one command. 
  
  I'm using the Clock widget in the qtile bar as so:
  ``` python 
          widget.Clock(format="%A %d %b %Y %H:%M:%S %z"),
  ```
  
  Updating the timezone with `tzupdate` however does not change the timezone on the Clock widget. It requires restarting qtile in order to get this done. I would expect qtile to poll the current system timezone at each tik.
  
  ### Required:
  
  - [X] I have searched past issues to see if this bug has already been reported.
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `libqtile/widget/clock.py`
  Content:
  ```
  1 # Copyright (c) 2010 Aldo Cortesi
  2 # Copyright (c) 2012 Andrew Grigorev
  3 # Copyright (c) 2014 Sean Vig
  4 # Copyright (c) 2014 Tycho Andersen
  5 #
  6 # Permission is hereby granted, free of charge, to any person obtaining a copy
  7 # of this software and associated documentation files (the "Software"), to deal
  8 # in the Software without restriction, including without limitation the rights
  9 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 # copies of the Software, and to permit persons to whom the Software is
  11 # furnished to do so, subject to the following conditions:
  12 #
  13 # The above copyright notice and this permission notice shall be included in
  14 # all copies or substantial portions of the Software.
  15 #
  16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  22 # SOFTWARE.
  23 
  24 import sys
  25 import time
  26 from datetime import datetime, timedelta, timezone
  27 
  28 from libqtile.log_utils import logger
  29 from libqtile.widget import base
  30 
  31 try:
  32     import pytz
  33 except ImportError:
  34     pass
  35 
  36 try:
  37     import dateutil.tz
  38 except ImportError:
  39     pass
  40 
  41 
  42 class Clock(base.InLoopPollText):
  43     """A simple but flexible text-based clock"""
  44 
  45     defaults = [
  46         ("format", "%H:%M", "A Python datetime format string"),
  47         ("update_interval", 1.0, "Update interval for the clock"),
  48         (
  49             "timezone",
  50             None,
  51             "The timezone to use for this clock, either as"
  52             ' string if pytz or dateutil is installed (e.g. "US/Central" or'
  53             " anything in /usr/share/zoneinfo), or as tzinfo (e.g."
  54             " datetime.timezone.utc). None means the system local timezone and is"
  55             " the default.",
  56         ),
  57     ]
  58     DELTA = timedelta(seconds=0.5)
  59 
  60     def __init__(self, **config):
  61         base.InLoopPollText.__init__(self, **config)
  62         self.add_defaults(Clock.defaults)
  63         if isinstance(self.timezone, str):
  64             if "pytz" in sys.modules:
  65                 self.timezone = pytz.timezone(self.timezone)
  66             elif "dateutil" in sys.modules:
  67                 self.timezone = dateutil.tz.gettz(self.timezone)
  68             else:
  69                 logger.warning(
  70                     "Clock widget can not infer its timezone from a"
  71                     " string without pytz or dateutil. Install one"
  72                     " of these libraries, or give it a"
  73                     " datetime.tzinfo instance."
  74                 )
  75         if self.timezone is None:
  76             logger.debug("Defaulting to the system local timezone.")
  77 
  78     def tick(self):
  79         self.update(self.poll())
  80         return self.update_interval - time.time() % self.update_interval
  81 
  82     # adding .5 to get a proper seconds value because glib could
  83     # theoreticaly call our method too early and we could get something
  84     # like (x-1).999 instead of x.000
  85     def poll(self):
  86         if self.timezone:
  87             now = datetime.now(timezone.utc).astimezone(self.timezone)
  88         else:
  89             now = datetime.now(timezone.utc).astimezone()
  90         return (now + self.DELTA).strftime(self.format)
  91
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/libqtile/widget/clock.py b/libqtile/widget/clock.py
  --- a/libqtile/widget/clock.py
  +++ b/libqtile/widget/clock.py
  @@ -20,11 +20,13 @@
   # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
   # SOFTWARE.
  +from __future__ import annotations
   
   import sys
   import time
  -from datetime import datetime, timedelta, timezone
  +from datetime import datetime, timedelta, timezone, tzinfo
   
  +from libqtile.command.base import expose_command
   from libqtile.log_utils import logger
   from libqtile.widget import base
   
  @@ -60,11 +62,24 @@
       def __init__(self, **config):
           base.InLoopPollText.__init__(self, **config)
           self.add_defaults(Clock.defaults)
  -        if isinstance(self.timezone, str):
  +        self.timezone = self._lift_timezone(self.timezone)
  +
  +        if self.timezone is None:
  +            logger.debug("Defaulting to the system local timezone.")
  +
  +    def _lift_timezone(self, timezone):
  +        if isinstance(timezone, tzinfo):
  +            return timezone
  +        elif isinstance(timezone, str):
  +            # Empty string can be used to force use of system time
  +            if not timezone:
  +                return None
  +
  +            # A string timezone needs to be converted to a tzinfo object
               if "pytz" in sys.modules:
  -                self.timezone = pytz.timezone(self.timezone)
  +                return pytz.timezone(timezone)
               elif "dateutil" in sys.modules:
  -                self.timezone = dateutil.tz.gettz(self.timezone)
  +                return dateutil.tz.gettz(timezone)
               else:
                   logger.warning(
                       "Clock widget can not infer its timezone from a"
  @@ -72,8 +87,12 @@
                       " of these libraries, or give it a"
                       " datetime.tzinfo instance."
                   )
  -        if self.timezone is None:
  -            logger.debug("Defaulting to the system local timezone.")
  +        elif timezone is None:
  +            pass
  +        else:
  +            logger.warning("Invalid timezone value %s.", timezone)
  +
  +        return None
   
       def tick(self):
           self.update(self.poll())
  @@ -88,3 +107,27 @@
           else:
               now = datetime.now(timezone.utc).astimezone()
           return (now + self.DELTA).strftime(self.format)
  +
  +    @expose_command
  +    def update_timezone(self, timezone: str | tzinfo | None = None):
  +        """
  +        Force the clock to update timezone information.
  +
  +        If the method is called with no arguments then the widget will reload
  +        the timzeone set on the computer (e.g. via ``timedatectl set-timezone ..``).
  +        This will have no effect if you have previously set a ``timezone`` value.
  +
  +        Alternatively, you can pass a timezone string (e.g. ``"Europe/Lisbon"``) to change
  +        the specified timezone. Setting this to an empty string will cause the clock
  +        to rely on the system timezone.
  +        """
  +        self.timezone = self._lift_timezone(timezone)
  +
  +        # Force python to update timezone info (e.g. if system time has changed)
  +        time.tzset()
  +        self.update(self.poll())
  +
  +    @expose_command
  +    def use_system_timezone(self):
  +        """Force clock to use system timezone."""
  +        self.update_timezone("")
  
verification_info: {"golden_diff": "diff --git a/libqtile/widget/clock.py b/libqtile/widget/clock.py\n--- a/libqtile/widget/clock.py\n+++ b/libqtile/widget/clock.py\n@@ -20,11 +20,13 @@\n # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n # SOFTWARE.\n+from __future__ import annotations\n \n import sys\n import time\n-from datetime import datetime, timedelta, timezone\n+from datetime import datetime, timedelta, timezone, tzinfo\n \n+from libqtile.command.base import expose_command\n from libqtile.log_utils import logger\n from libqtile.widget import base\n \n@@ -60,11 +62,24 @@\n     def __init__(self, **config):\n         base.InLoopPollText.__init__(self, **config)\n         self.add_defaults(Clock.defaults)\n-        if isinstance(self.timezone, str):\n+        self.timezone = self._lift_timezone(self.timezone)\n+\n+        if self.timezone is None:\n+            logger.debug(\"Defaulting to the system local timezone.\")\n+\n+    def _lift_timezone(self, timezone):\n+        if isinstance(timezone, tzinfo):\n+            return timezone\n+        elif isinstance(timezone, str):\n+            # Empty string can be used to force use of system time\n+            if not timezone:\n+                return None\n+\n+            # A string timezone needs to be converted to a tzinfo object\n             if \"pytz\" in sys.modules:\n-                self.timezone = pytz.timezone(self.timezone)\n+                return pytz.timezone(timezone)\n             elif \"dateutil\" in sys.modules:\n-                self.timezone = dateutil.tz.gettz(self.timezone)\n+                return dateutil.tz.gettz(timezone)\n             else:\n                 logger.warning(\n                     \"Clock widget can not infer its timezone from a\"\n@@ -72,8 +87,12 @@\n                     \" of these libraries, or give it a\"\n                     \" datetime.tzinfo instance.\"\n                 )\n-        if self.timezone is None:\n-            logger.debug(\"Defaulting to the system local timezone.\")\n+        elif timezone is None:\n+            pass\n+        else:\n+            logger.warning(\"Invalid timezone value %s.\", timezone)\n+\n+        return None\n \n     def tick(self):\n         self.update(self.poll())\n@@ -88,3 +107,27 @@\n         else:\n             now = datetime.now(timezone.utc).astimezone()\n         return (now + self.DELTA).strftime(self.format)\n+\n+    @expose_command\n+    def update_timezone(self, timezone: str | tzinfo | None = None):\n+        \"\"\"\n+        Force the clock to update timezone information.\n+\n+        If the method is called with no arguments then the widget will reload\n+        the timzeone set on the computer (e.g. via ``timedatectl set-timezone ..``).\n+        This will have no effect if you have previously set a ``timezone`` value.\n+\n+        Alternatively, you can pass a timezone string (e.g. ``\"Europe/Lisbon\"``) to change\n+        the specified timezone. Setting this to an empty string will cause the clock\n+        to rely on the system timezone.\n+        \"\"\"\n+        self.timezone = self._lift_timezone(timezone)\n+\n+        # Force python to update timezone info (e.g. if system time has changed)\n+        time.tzset()\n+        self.update(self.poll())\n+\n+    @expose_command\n+    def use_system_timezone(self):\n+        \"\"\"Force clock to use system timezone.\"\"\"\n+        self.update_timezone(\"\")\n", "issue": "Clock and tzupdate \n### The issue:\n\nqtile version:\r\n0.21.0\r\n\r\nThese days I need to travel with my system and have the need to update my timezone in order to work with my calendar. I'm using `tzupdate` which easily updates my timezone with one command. \r\n\r\nI'm using the Clock widget in the qtile bar as so:\r\n``` python \r\n        widget.Clock(format=\"%A %d %b %Y %H:%M:%S %z\"),\r\n```\r\n\r\nUpdating the timezone with `tzupdate` however does not change the timezone on the Clock widget. It requires restarting qtile in order to get this done. I would expect qtile to poll the current system timezone at each tik.\n\n### Required:\n\n- [X] I have searched past issues to see if this bug has already been reported.\n", "before_files": [{"content": "# Copyright (c) 2010 Aldo Cortesi\n# Copyright (c) 2012 Andrew Grigorev\n# Copyright (c) 2014 Sean Vig\n# Copyright (c) 2014 Tycho Andersen\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n# SOFTWARE.\n\nimport sys\nimport time\nfrom datetime import datetime, timedelta, timezone\n\nfrom libqtile.log_utils import logger\nfrom libqtile.widget import base\n\ntry:\n    import pytz\nexcept ImportError:\n    pass\n\ntry:\n    import dateutil.tz\nexcept ImportError:\n    pass\n\n\nclass Clock(base.InLoopPollText):\n    \"\"\"A simple but flexible text-based clock\"\"\"\n\n    defaults = [\n        (\"format\", \"%H:%M\", \"A Python datetime format string\"),\n        (\"update_interval\", 1.0, \"Update interval for the clock\"),\n        (\n            \"timezone\",\n            None,\n            \"The timezone to use for this clock, either as\"\n            ' string if pytz or dateutil is installed (e.g. \"US/Central\" or'\n            \" anything in /usr/share/zoneinfo), or as tzinfo (e.g.\"\n            \" datetime.timezone.utc). None means the system local timezone and is\"\n            \" the default.\",\n        ),\n    ]\n    DELTA = timedelta(seconds=0.5)\n\n    def __init__(self, **config):\n        base.InLoopPollText.__init__(self, **config)\n        self.add_defaults(Clock.defaults)\n        if isinstance(self.timezone, str):\n            if \"pytz\" in sys.modules:\n                self.timezone = pytz.timezone(self.timezone)\n            elif \"dateutil\" in sys.modules:\n                self.timezone = dateutil.tz.gettz(self.timezone)\n            else:\n                logger.warning(\n                    \"Clock widget can not infer its timezone from a\"\n                    \" string without pytz or dateutil. Install one\"\n                    \" of these libraries, or give it a\"\n                    \" datetime.tzinfo instance.\"\n                )\n        if self.timezone is None:\n            logger.debug(\"Defaulting to the system local timezone.\")\n\n    def tick(self):\n        self.update(self.poll())\n        return self.update_interval - time.time() % self.update_interval\n\n    # adding .5 to get a proper seconds value because glib could\n    # theoreticaly call our method too early and we could get something\n    # like (x-1).999 instead of x.000\n    def poll(self):\n        if self.timezone:\n            now = datetime.now(timezone.utc).astimezone(self.timezone)\n        else:\n            now = datetime.now(timezone.utc).astimezone()\n        return (now + self.DELTA).strftime(self.format)\n", "path": "libqtile/widget/clock.py"}], "after_files": [{"content": "# Copyright (c) 2010 Aldo Cortesi\n# Copyright (c) 2012 Andrew Grigorev\n# Copyright (c) 2014 Sean Vig\n# Copyright (c) 2014 Tycho Andersen\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n# SOFTWARE.\nfrom __future__ import annotations\n\nimport sys\nimport time\nfrom datetime import datetime, timedelta, timezone, tzinfo\n\nfrom libqtile.command.base import expose_command\nfrom libqtile.log_utils import logger\nfrom libqtile.widget import base\n\ntry:\n    import pytz\nexcept ImportError:\n    pass\n\ntry:\n    import dateutil.tz\nexcept ImportError:\n    pass\n\n\nclass Clock(base.InLoopPollText):\n    \"\"\"A simple but flexible text-based clock\"\"\"\n\n    defaults = [\n        (\"format\", \"%H:%M\", \"A Python datetime format string\"),\n        (\"update_interval\", 1.0, \"Update interval for the clock\"),\n        (\n            \"timezone\",\n            None,\n            \"The timezone to use for this clock, either as\"\n            ' string if pytz or dateutil is installed (e.g. \"US/Central\" or'\n            \" anything in /usr/share/zoneinfo), or as tzinfo (e.g.\"\n            \" datetime.timezone.utc). None means the system local timezone and is\"\n            \" the default.\",\n        ),\n    ]\n    DELTA = timedelta(seconds=0.5)\n\n    def __init__(self, **config):\n        base.InLoopPollText.__init__(self, **config)\n        self.add_defaults(Clock.defaults)\n        self.timezone = self._lift_timezone(self.timezone)\n\n        if self.timezone is None:\n            logger.debug(\"Defaulting to the system local timezone.\")\n\n    def _lift_timezone(self, timezone):\n        if isinstance(timezone, tzinfo):\n            return timezone\n        elif isinstance(timezone, str):\n            # Empty string can be used to force use of system time\n            if not timezone:\n                return None\n\n            # A string timezone needs to be converted to a tzinfo object\n            if \"pytz\" in sys.modules:\n                return pytz.timezone(timezone)\n            elif \"dateutil\" in sys.modules:\n                return dateutil.tz.gettz(timezone)\n            else:\n                logger.warning(\n                    \"Clock widget can not infer its timezone from a\"\n                    \" string without pytz or dateutil. Install one\"\n                    \" of these libraries, or give it a\"\n                    \" datetime.tzinfo instance.\"\n                )\n        elif timezone is None:\n            pass\n        else:\n            logger.warning(\"Invalid timezone value %s.\", timezone)\n\n        return None\n\n    def tick(self):\n        self.update(self.poll())\n        return self.update_interval - time.time() % self.update_interval\n\n    # adding .5 to get a proper seconds value because glib could\n    # theoreticaly call our method too early and we could get something\n    # like (x-1).999 instead of x.000\n    def poll(self):\n        if self.timezone:\n            now = datetime.now(timezone.utc).astimezone(self.timezone)\n        else:\n            now = datetime.now(timezone.utc).astimezone()\n        return (now + self.DELTA).strftime(self.format)\n\n    @expose_command\n    def update_timezone(self, timezone: str | tzinfo | None = None):\n        \"\"\"\n        Force the clock to update timezone information.\n\n        If the method is called with no arguments then the widget will reload\n        the timzeone set on the computer (e.g. via ``timedatectl set-timezone ..``).\n        This will have no effect if you have previously set a ``timezone`` value.\n\n        Alternatively, you can pass a timezone string (e.g. ``\"Europe/Lisbon\"``) to change\n        the specified timezone. Setting this to an empty string will cause the clock\n        to rely on the system timezone.\n        \"\"\"\n        self.timezone = self._lift_timezone(timezone)\n\n        # Force python to update timezone info (e.g. if system time has changed)\n        time.tzset()\n        self.update(self.poll())\n\n    @expose_command\n    def use_system_timezone(self):\n        \"\"\"Force clock to use system timezone.\"\"\"\n        self.update_timezone(\"\")\n", "path": "libqtile/widget/clock.py"}]}