We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
clock.py:269: PytzUsageWarning: The zone attribute is specific to pytz's interface
**Describe the bug**
clock.py:269: PytzUsageWarning: The zone attribute is specific to pytz's interface; please migrate to a new time zone provider. For more details on how to do so, see https://pytz-deprecation-shim.readthedocs.io/en/latest/migration.html

**Your py3status version**
py3status version 3.47 (python 3.8.10) on i3
Ubuntu 20.04

**To Reproduce**
Steps to reproduce the behavior along with your py3status configuration (filter out any private values):
1. Run clock.py module inside of terminal emulator.

**Expected behavior**
No warning shown.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `py3status/modules/clock.py`
Content:
```
1 """
2 Display date and time.
3 
4 This module allows one or more datetimes to be displayed.
5 All datetimes share the same format_time but can set their own timezones.
6 Timezones are defined in the `format` using the TZ name in squiggly brackets eg
7 `{GMT}`, `{Portugal}`, `{Europe/Paris}`, `{America/Argentina/Buenos_Aires}`.
8 
9 ISO-3166 two letter country codes eg `{de}` can also be used but if more than
10 one timezone exists for the country eg `{us}` the first one will be selected.
11 
12 `{Local}` can be used for the local settings of your computer.
13 
14 Note: Timezones are case sensitive
15 
16 A full list of timezones can be found at
17 https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
18 
19 Configuration parameters:
20     block_hours: length of time period for all blocks in hours (default 12)
21     blocks: a string, where each character represents time period
22         from the start of a time period.
23         (default '🕛🕧🕐🕜🕑🕝🕒🕞🕓🕟🕔🕠🕕🕡🕖🕢🕗🕣🕘🕤🕙🕥🕚🕦')
24     button_change_format: button that switches format used setting to None
25         disables (default 1)
26     button_change_time_format: button that switches format_time used. Setting
27         to None disables (default 2)
28     button_reset: button that switches display to the first timezone. Setting
29         to None disables (default 3)
30     cycle: If more than one display then how many seconds between changing the
31         display (default 0)
32     format: defines the timezones displayed. This can be a single string or a
33         list.  If a list is supplied then the formats can be cycled through
34         using `cycle` or by button click.  (default '{Local}')
35     format_time: format to use for the time, strftime directives such as `%H`
36         can be used this can be either a string or to allow multiple formats as
37         a list.  The one used can be changed by button click.
38         *(default ['[{name_unclear} ]%c', '[{name_unclear} ]%x %X',
39         '[{name_unclear} ]%a %H:%M', '[{name_unclear} ]{icon}'])*
40     locale: Override the system locale. Examples:
41         when set to 'fr_FR' %a on Tuesday is 'mar.'.
42         (default None)
43     round_to_nearest_block: defines how a block icon is chosen. Examples:
44         when set to True,  '13:14' is '🕐', '13:16' is '🕜' and '13:31' is '🕜';
45         when set to False, '13:14' is '🕐', '13:16' is '🕐' and '13:31' is '🕜'.
46         (default True)
47 
48 Format placeholders:
49     {icon} a character representing the time from `blocks`
50     {name} friendly timezone name eg `Buenos Aires`
51     {name_unclear} friendly timezone name eg `Buenos Aires` but is empty if
52         only one timezone is provided
53     {timezone} full timezone name eg `America/Argentina/Buenos_Aires`
54     {timezone_unclear} full timezone name eg `America/Argentina/Buenos_Aires`
55         but is empty if only one timezone is provided
56 
57 Requires:
58     pytz: cross platform time zone library for python
59     tzlocal: tzinfo object for the local timezone
60 
61 Examples:
62 ```
63 # cycling through London, Warsaw, Tokyo
64 clock {
65     cycle = 30
66     format = ["{Europe/London}", "{Europe/Warsaw}", "{Asia/Tokyo}"]
67     format_time = "{name} %H:%M"
68 }
69 
70 # Show the time and date in New York
71 clock {
72    format = "Big Apple {America/New_York}"
73    format_time = "%Y-%m-%d %H:%M:%S"
74 }
75 
76 # wall clocks
77 clock {
78     format = "{Asia/Calcutta} {Africa/Nairobi} {Asia/Bangkok}"
79     format_time = "{name} {icon}"
80 }
81 ```
82 
83 @author tobes
84 @license BSD
85 
86 SAMPLE OUTPUT
87 {'full_text': 'Sun 15 Jan 2017 23:27:17 GMT'}
88 
89 london
90 {'full_text': 'Thursday Feb 23 1:42 AM London'}
91 """
92 
93 import locale
94 import re
95 import time
96 from datetime import datetime
97 
98 import pytz
99 import tzlocal
100 
101 CLOCK_BLOCKS = "🕛🕧🕐🕜🕑🕝🕒🕞🕓🕟🕔🕠🕕🕡🕖🕢🕗🕣🕘🕤🕙🕥🕚🕦"
102 
103 
104 class Py3status:
105     """ """
106 
107     # available configuration parameters
108     block_hours = 12
109     blocks = CLOCK_BLOCKS
110     button_change_format = 1
111     button_change_time_format = 2
112     button_reset = 3
113     cycle = 0
114     format = "{Local}"
115     format_time = [
116         "[{name_unclear} ]%c",
117         "[{name_unclear} ]%x %X",
118         "[{name_unclear} ]%a %H:%M",
119         "[{name_unclear} ]{icon}",
120     ]
121     locale = None
122     round_to_nearest_block = True
123 
124     def post_config_hook(self):
125         if self.locale is not None:
126             locale.setlocale(locale.LC_TIME, self.locale)
127 
128         # Multiple clocks are possible that can be cycled through
129         if not isinstance(self.format, list):
130             self.format = [self.format]
131         # if only one item we don't need to cycle
132         if len(self.format) == 1:
133             self.cycle = 0
134         # find any declared timezones eg {Europe/London}
135         self._fmts = set()
136         for fmt in self.format:
137             self._fmts.update(self.py3.get_placeholders_list(fmt))
138 
139         self.multiple_tz = len(self._fmts) > 1
140 
141         if not isinstance(self.format_time, list):
142             self.format_time = [self.format_time]
143 
144         # workout how often in seconds we will need to do an update to keep the
145         # display fresh
146         self.time_deltas = []
147         for format in self.format_time:
148             format_time = re.sub(r"{([^}]*)}", "", format)
149             format_time = format_time.replace("%%", "")
150             if "%f" in format_time:
151                 # microseconds
152                 time_delta = 0
153             elif "%S" in format_time:
154                 # seconds
155                 time_delta = 1
156             elif "%s" in format_time:
157                 # seconds since unix epoch start
158                 time_delta = 1
159             elif "%T" in format_time:
160                 # seconds included in "%H:%M:%S"
161                 time_delta = 1
162             elif "%c" in format_time:
163                 # Locale’s appropriate date and time representation
164                 time_delta = 1
165             elif "%X" in format_time:
166                 # Locale’s appropriate time representation
167                 time_delta = 1
168             else:
169                 time_delta = 60
170             self.time_deltas.append(time_delta)
171 
172         # If we have saved details we use them.
173         saved_format = self.py3.storage_get("time_format")
174         if saved_format in self.format_time:
175             self.active_time_format = self.format_time.index(saved_format)
176         else:
177             self.active_time_format = 0
178 
179         saved_timezone = self.py3.storage_get("timezone")
180         if saved_timezone in self.format:
181             self.active = self.format.index(saved_timezone)
182         else:
183             self.active = 0
184 
185         # reset the cycle time
186         self._cycle_time = time.time() + self.cycle
187 
188     def _get_timezone(self, tz):
189         """
190         Find and return the time zone if possible
191         """
192         # special Local timezone
193         if tz == "Local":
194             try:
195                 return tzlocal.get_localzone()
196             except pytz.UnknownTimeZoneError:
197                 return "?"
198 
199         # we can use a country code to get tz
200         # FIXME this is broken for multi-timezone countries eg US
201         # for now we just grab the first one
202         if len(tz) == 2:
203             try:
204                 zones = pytz.country_timezones(tz)
205             except KeyError:
206                 return "?"
207             tz = zones[0]
208 
209         # get the timezone
210         try:
211             zone = pytz.timezone(tz)
212         except pytz.UnknownTimeZoneError:
213             return "?"
214         return zone
215 
216     def _change_active(self, diff):
217         self.active = (self.active + diff) % len(self.format)
218         # reset the cycle time
219         self._cycle_time = time.time() + self.cycle
220         # save the active format
221         timezone = self.format[self.active]
222         self.py3.storage_set("timezone", timezone)
223 
224     def on_click(self, event):
225         """
226         Switch the displayed module or pass the event on to the active module
227         """
228         if event["button"] == self.button_reset:
229             self._change_active(0)
230         elif event["button"] == self.button_change_time_format:
231             self.active_time_format += 1
232             if self.active_time_format >= len(self.format_time):
233                 self.active_time_format = 0
234             # save the active format_time
235             time_format = self.format_time[self.active_time_format]
236             self.py3.storage_set("time_format", time_format)
237         elif event["button"] == self.button_change_format:
238             self._change_active(1)
239 
240     def clock(self):
241 
242         # cycling
243         if self.cycle and time.time() >= self._cycle_time:
244             self._change_active(1)
245             self._cycle_time = time.time() + self.cycle
246 
247         # update our times
248         times = {}
249         for name in self._fmts:
250             zone = self._get_timezone(name)
251             if zone == "?":
252                 times[name] = "?"
253             else:
254                 t = datetime.now(zone)
255                 format_time = self.format_time[self.active_time_format]
256                 icon = None
257                 if self.py3.format_contains(format_time, "icon"):
258                     # calculate the decimal hour
259                     h = t.hour + t.minute / 60
260                     if self.round_to_nearest_block:
261                         h += self.block_hours / len(self.blocks) / 2
262                     # make 12 hourly etc
263                     h = h % self.block_hours
264                     idx = int(h / self.block_hours * len(self.blocks))
265                     icon = self.blocks[idx]
266 
267                 try:
268                     # tzlocal < 3.0
269                     timezone = zone.zone
270                 except AttributeError:
271                     # tzlocal >= 3.0
272                     timezone = zone.key
273                 tzname = timezone.split("/")[-1].replace("_", " ")
274 
275                 if self.multiple_tz:
276                     name_unclear = tzname
277                     timezone_unclear = timezone
278                 else:
279                     name_unclear = ""
280                     timezone_unclear = ""
281 
282                 format_time = self.py3.safe_format(
283                     format_time,
284                     dict(
285                         icon=icon,
286                         name=tzname,
287                         name_unclear=name_unclear,
288                         timezone=timezone,
289                         timezone_unclear=timezone_unclear,
290                     ),
291                 )
292 
293                 if self.py3.is_composite(format_time):
294                     for item in format_time:
295                         item["full_text"] = t.strftime(item["full_text"])
296                 else:
297                     format_time = t.strftime(format_time)
298                 times[name] = format_time
299 
300         # work out when we need to update
301         timeout = self.py3.time_in(sync_to=self.time_deltas[self.active_time_format])
302 
303         # if cycling we need to make sure we update when they are needed
304         if self.cycle:
305             cycle_timeout = self._cycle_time
306             timeout = min(timeout, cycle_timeout)
307 
308         return {
309             "full_text": self.py3.safe_format(self.format[self.active], times),
310             "cached_until": timeout,
311         }
312 
313 
314 if __name__ == "__main__":
315     """
316     Run module in test mode.
317     """
318     from py3status.module_test import module_test
319 
320     module_test(Py3status)
321
```
--- 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()

```

diff --git a/py3status/modules/clock.py b/py3status/modules/clock.py
--- a/py3status/modules/clock.py
+++ b/py3status/modules/clock.py
@@ -6,12 +6,11 @@
 Timezones are defined in the `format` using the TZ name in squiggly brackets eg
 `{GMT}`, `{Portugal}`, `{Europe/Paris}`, `{America/Argentina/Buenos_Aires}`.
 
-ISO-3166 two letter country codes eg `{de}` can also be used but if more than
-one timezone exists for the country eg `{us}` the first one will be selected.
+See https://docs.python.org/3/library/zoneinfo.html for supported formats.
 
 `{Local}` can be used for the local settings of your computer.
 
-Note: Timezones are case sensitive
+Note: Timezones are case sensitive!
 
 A full list of timezones can be found at
 https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
@@ -54,10 +53,6 @@
     {timezone_unclear} full timezone name eg `America/Argentina/Buenos_Aires`
         but is empty if only one timezone is provided
 
-Requires:
-    pytz: cross platform time zone library for python
-    tzlocal: tzinfo object for the local timezone
-
 Examples:
 ```
 # cycling through London, Warsaw, Tokyo
@@ -80,7 +75,7 @@
 }
 ```
 
-@author tobes
+@author tobes ultrabug
 @license BSD
 
 SAMPLE OUTPUT
@@ -95,8 +90,11 @@
 import time
 from datetime import datetime
 
-import pytz
-import tzlocal
+try:
+    import zoneinfo
+# Fall back for python 3.7 and python 3.8
+except ImportError:
+    from backports import zoneinfo
 
 CLOCK_BLOCKS = "🕛🕧🕐🕜🕑🕝🕒🕞🕓🕟🕔🕠🕕🕡🕖🕢🕗🕣🕘🕤🕙🕥🕚🕦"
 
@@ -192,24 +190,13 @@
         # special Local timezone
         if tz == "Local":
             try:
-                return tzlocal.get_localzone()
-            except pytz.UnknownTimeZoneError:
+                return zoneinfo.ZoneInfo("localtime")
+            except zoneinfo.ZoneInfoNotFoundError:
                 return "?"
-
-        # we can use a country code to get tz
-        # FIXME this is broken for multi-timezone countries eg US
-        # for now we just grab the first one
-        if len(tz) == 2:
-            try:
-                zones = pytz.country_timezones(tz)
-            except KeyError:
-                return "?"
-            tz = zones[0]
-
         # get the timezone
         try:
-            zone = pytz.timezone(tz)
-        except pytz.UnknownTimeZoneError:
+            zone = zoneinfo.ZoneInfo(tz)
+        except zoneinfo.ZoneInfoNotFoundError:
             return "?"
         return zone
 
@@ -264,12 +251,7 @@
                     idx = int(h / self.block_hours * len(self.blocks))
                     icon = self.blocks[idx]
 
-                try:
-                    # tzlocal < 3.0
-                    timezone = zone.zone
-                except AttributeError:
-                    # tzlocal >= 3.0
-                    timezone = zone.key
+                timezone = zone.key
                 tzname = timezone.split("/")[-1].replace("_", " ")
 
                 if self.multiple_tz:

{"golden_diff": "diff --git a/py3status/modules/clock.py b/py3status/modules/clock.py\n--- a/py3status/modules/clock.py\n+++ b/py3status/modules/clock.py\n@@ -6,12 +6,11 @@\n Timezones are defined in the `format` using the TZ name in squiggly brackets eg\n `{GMT}`, `{Portugal}`, `{Europe/Paris}`, `{America/Argentina/Buenos_Aires}`.\n \n-ISO-3166 two letter country codes eg `{de}` can also be used but if more than\n-one timezone exists for the country eg `{us}` the first one will be selected.\n+See https://docs.python.org/3/library/zoneinfo.html for supported formats.\n \n `{Local}` can be used for the local settings of your computer.\n \n-Note: Timezones are case sensitive\n+Note: Timezones are case sensitive!\n \n A full list of timezones can be found at\n https://en.wikipedia.org/wiki/List_of_tz_database_time_zones\n@@ -54,10 +53,6 @@\n     {timezone_unclear} full timezone name eg `America/Argentina/Buenos_Aires`\n         but is empty if only one timezone is provided\n \n-Requires:\n-    pytz: cross platform time zone library for python\n-    tzlocal: tzinfo object for the local timezone\n-\n Examples:\n ```\n # cycling through London, Warsaw, Tokyo\n@@ -80,7 +75,7 @@\n }\n ```\n \n-@author tobes\n+@author tobes ultrabug\n @license BSD\n \n SAMPLE OUTPUT\n@@ -95,8 +90,11 @@\n import time\n from datetime import datetime\n \n-import pytz\n-import tzlocal\n+try:\n+    import zoneinfo\n+# Fall back for python 3.7 and python 3.8\n+except ImportError:\n+    from backports import zoneinfo\n \n CLOCK_BLOCKS = \"\ud83d\udd5b\ud83d\udd67\ud83d\udd50\ud83d\udd5c\ud83d\udd51\ud83d\udd5d\ud83d\udd52\ud83d\udd5e\ud83d\udd53\ud83d\udd5f\ud83d\udd54\ud83d\udd60\ud83d\udd55\ud83d\udd61\ud83d\udd56\ud83d\udd62\ud83d\udd57\ud83d\udd63\ud83d\udd58\ud83d\udd64\ud83d\udd59\ud83d\udd65\ud83d\udd5a\ud83d\udd66\"\n \n@@ -192,24 +190,13 @@\n         # special Local timezone\n         if tz == \"Local\":\n             try:\n-                return tzlocal.get_localzone()\n-            except pytz.UnknownTimeZoneError:\n+                return zoneinfo.ZoneInfo(\"localtime\")\n+            except zoneinfo.ZoneInfoNotFoundError:\n                 return \"?\"\n-\n-        # we can use a country code to get tz\n-        # FIXME this is broken for multi-timezone countries eg US\n-        # for now we just grab the first one\n-        if len(tz) == 2:\n-            try:\n-                zones = pytz.country_timezones(tz)\n-            except KeyError:\n-                return \"?\"\n-            tz = zones[0]\n-\n         # get the timezone\n         try:\n-            zone = pytz.timezone(tz)\n-        except pytz.UnknownTimeZoneError:\n+            zone = zoneinfo.ZoneInfo(tz)\n+        except zoneinfo.ZoneInfoNotFoundError:\n             return \"?\"\n         return zone\n \n@@ -264,12 +251,7 @@\n                     idx = int(h / self.block_hours * len(self.blocks))\n                     icon = self.blocks[idx]\n \n-                try:\n-                    # tzlocal < 3.0\n-                    timezone = zone.zone\n-                except AttributeError:\n-                    # tzlocal >= 3.0\n-                    timezone = zone.key\n+                timezone = zone.key\n                 tzname = timezone.split(\"/\")[-1].replace(\"_\", \" \")\n \n                 if self.multiple_tz:\n", "issue": "clock.py:269: PytzUsageWarning: The zone attribute is specific to pytz's interface\n**Describe the bug**\r\nclock.py:269: PytzUsageWarning: The zone attribute is specific to pytz's interface; please migrate to a new time zone provider. For more details on how to do so, see https://pytz-deprecation-shim.readthedocs.io/en/latest/migration.html\r\n\r\n**Your py3status version**\r\npy3status version 3.47 (python 3.8.10) on i3\r\nUbuntu 20.04\r\n\r\n**To Reproduce**\r\nSteps to reproduce the behavior along with your py3status configuration (filter out any private values):\r\n1. Run clock.py module inside of terminal emulator.\r\n\r\n**Expected behavior**\r\nNo warning shown.\r\n\n", "before_files": [{"content": "\"\"\"\nDisplay date and time.\n\nThis module allows one or more datetimes to be displayed.\nAll datetimes share the same format_time but can set their own timezones.\nTimezones are defined in the `format` using the TZ name in squiggly brackets eg\n`{GMT}`, `{Portugal}`, `{Europe/Paris}`, `{America/Argentina/Buenos_Aires}`.\n\nISO-3166 two letter country codes eg `{de}` can also be used but if more than\none timezone exists for the country eg `{us}` the first one will be selected.\n\n`{Local}` can be used for the local settings of your computer.\n\nNote: Timezones are case sensitive\n\nA full list of timezones can be found at\nhttps://en.wikipedia.org/wiki/List_of_tz_database_time_zones\n\nConfiguration parameters:\n    block_hours: length of time period for all blocks in hours (default 12)\n    blocks: a string, where each character represents time period\n        from the start of a time period.\n        (default '\ud83d\udd5b\ud83d\udd67\ud83d\udd50\ud83d\udd5c\ud83d\udd51\ud83d\udd5d\ud83d\udd52\ud83d\udd5e\ud83d\udd53\ud83d\udd5f\ud83d\udd54\ud83d\udd60\ud83d\udd55\ud83d\udd61\ud83d\udd56\ud83d\udd62\ud83d\udd57\ud83d\udd63\ud83d\udd58\ud83d\udd64\ud83d\udd59\ud83d\udd65\ud83d\udd5a\ud83d\udd66')\n    button_change_format: button that switches format used setting to None\n        disables (default 1)\n    button_change_time_format: button that switches format_time used. Setting\n        to None disables (default 2)\n    button_reset: button that switches display to the first timezone. Setting\n        to None disables (default 3)\n    cycle: If more than one display then how many seconds between changing the\n        display (default 0)\n    format: defines the timezones displayed. This can be a single string or a\n        list.  If a list is supplied then the formats can be cycled through\n        using `cycle` or by button click.  (default '{Local}')\n    format_time: format to use for the time, strftime directives such as `%H`\n        can be used this can be either a string or to allow multiple formats as\n        a list.  The one used can be changed by button click.\n        *(default ['[{name_unclear} ]%c', '[{name_unclear} ]%x %X',\n        '[{name_unclear} ]%a %H:%M', '[{name_unclear} ]{icon}'])*\n    locale: Override the system locale. Examples:\n        when set to 'fr_FR' %a on Tuesday is 'mar.'.\n        (default None)\n    round_to_nearest_block: defines how a block icon is chosen. Examples:\n        when set to True,  '13:14' is '\ud83d\udd50', '13:16' is '\ud83d\udd5c' and '13:31' is '\ud83d\udd5c';\n        when set to False, '13:14' is '\ud83d\udd50', '13:16' is '\ud83d\udd50' and '13:31' is '\ud83d\udd5c'.\n        (default True)\n\nFormat placeholders:\n    {icon} a character representing the time from `blocks`\n    {name} friendly timezone name eg `Buenos Aires`\n    {name_unclear} friendly timezone name eg `Buenos Aires` but is empty if\n        only one timezone is provided\n    {timezone} full timezone name eg `America/Argentina/Buenos_Aires`\n    {timezone_unclear} full timezone name eg `America/Argentina/Buenos_Aires`\n        but is empty if only one timezone is provided\n\nRequires:\n    pytz: cross platform time zone library for python\n    tzlocal: tzinfo object for the local timezone\n\nExamples:\n```\n# cycling through London, Warsaw, Tokyo\nclock {\n    cycle = 30\n    format = [\"{Europe/London}\", \"{Europe/Warsaw}\", \"{Asia/Tokyo}\"]\n    format_time = \"{name} %H:%M\"\n}\n\n# Show the time and date in New York\nclock {\n   format = \"Big Apple {America/New_York}\"\n   format_time = \"%Y-%m-%d %H:%M:%S\"\n}\n\n# wall clocks\nclock {\n    format = \"{Asia/Calcutta} {Africa/Nairobi} {Asia/Bangkok}\"\n    format_time = \"{name} {icon}\"\n}\n```\n\n@author tobes\n@license BSD\n\nSAMPLE OUTPUT\n{'full_text': 'Sun 15 Jan 2017 23:27:17 GMT'}\n\nlondon\n{'full_text': 'Thursday Feb 23 1:42 AM London'}\n\"\"\"\n\nimport locale\nimport re\nimport time\nfrom datetime import datetime\n\nimport pytz\nimport tzlocal\n\nCLOCK_BLOCKS = \"\ud83d\udd5b\ud83d\udd67\ud83d\udd50\ud83d\udd5c\ud83d\udd51\ud83d\udd5d\ud83d\udd52\ud83d\udd5e\ud83d\udd53\ud83d\udd5f\ud83d\udd54\ud83d\udd60\ud83d\udd55\ud83d\udd61\ud83d\udd56\ud83d\udd62\ud83d\udd57\ud83d\udd63\ud83d\udd58\ud83d\udd64\ud83d\udd59\ud83d\udd65\ud83d\udd5a\ud83d\udd66\"\n\n\nclass Py3status:\n    \"\"\" \"\"\"\n\n    # available configuration parameters\n    block_hours = 12\n    blocks = CLOCK_BLOCKS\n    button_change_format = 1\n    button_change_time_format = 2\n    button_reset = 3\n    cycle = 0\n    format = \"{Local}\"\n    format_time = [\n        \"[{name_unclear} ]%c\",\n        \"[{name_unclear} ]%x %X\",\n        \"[{name_unclear} ]%a %H:%M\",\n        \"[{name_unclear} ]{icon}\",\n    ]\n    locale = None\n    round_to_nearest_block = True\n\n    def post_config_hook(self):\n        if self.locale is not None:\n            locale.setlocale(locale.LC_TIME, self.locale)\n\n        # Multiple clocks are possible that can be cycled through\n        if not isinstance(self.format, list):\n            self.format = [self.format]\n        # if only one item we don't need to cycle\n        if len(self.format) == 1:\n            self.cycle = 0\n        # find any declared timezones eg {Europe/London}\n        self._fmts = set()\n        for fmt in self.format:\n            self._fmts.update(self.py3.get_placeholders_list(fmt))\n\n        self.multiple_tz = len(self._fmts) > 1\n\n        if not isinstance(self.format_time, list):\n            self.format_time = [self.format_time]\n\n        # workout how often in seconds we will need to do an update to keep the\n        # display fresh\n        self.time_deltas = []\n        for format in self.format_time:\n            format_time = re.sub(r\"{([^}]*)}\", \"\", format)\n            format_time = format_time.replace(\"%%\", \"\")\n            if \"%f\" in format_time:\n                # microseconds\n                time_delta = 0\n            elif \"%S\" in format_time:\n                # seconds\n                time_delta = 1\n            elif \"%s\" in format_time:\n                # seconds since unix epoch start\n                time_delta = 1\n            elif \"%T\" in format_time:\n                # seconds included in \"%H:%M:%S\"\n                time_delta = 1\n            elif \"%c\" in format_time:\n                # Locale\u2019s appropriate date and time representation\n                time_delta = 1\n            elif \"%X\" in format_time:\n                # Locale\u2019s appropriate time representation\n                time_delta = 1\n            else:\n                time_delta = 60\n            self.time_deltas.append(time_delta)\n\n        # If we have saved details we use them.\n        saved_format = self.py3.storage_get(\"time_format\")\n        if saved_format in self.format_time:\n            self.active_time_format = self.format_time.index(saved_format)\n        else:\n            self.active_time_format = 0\n\n        saved_timezone = self.py3.storage_get(\"timezone\")\n        if saved_timezone in self.format:\n            self.active = self.format.index(saved_timezone)\n        else:\n            self.active = 0\n\n        # reset the cycle time\n        self._cycle_time = time.time() + self.cycle\n\n    def _get_timezone(self, tz):\n        \"\"\"\n        Find and return the time zone if possible\n        \"\"\"\n        # special Local timezone\n        if tz == \"Local\":\n            try:\n                return tzlocal.get_localzone()\n            except pytz.UnknownTimeZoneError:\n                return \"?\"\n\n        # we can use a country code to get tz\n        # FIXME this is broken for multi-timezone countries eg US\n        # for now we just grab the first one\n        if len(tz) == 2:\n            try:\n                zones = pytz.country_timezones(tz)\n            except KeyError:\n                return \"?\"\n            tz = zones[0]\n\n        # get the timezone\n        try:\n            zone = pytz.timezone(tz)\n        except pytz.UnknownTimeZoneError:\n            return \"?\"\n        return zone\n\n    def _change_active(self, diff):\n        self.active = (self.active + diff) % len(self.format)\n        # reset the cycle time\n        self._cycle_time = time.time() + self.cycle\n        # save the active format\n        timezone = self.format[self.active]\n        self.py3.storage_set(\"timezone\", timezone)\n\n    def on_click(self, event):\n        \"\"\"\n        Switch the displayed module or pass the event on to the active module\n        \"\"\"\n        if event[\"button\"] == self.button_reset:\n            self._change_active(0)\n        elif event[\"button\"] == self.button_change_time_format:\n            self.active_time_format += 1\n            if self.active_time_format >= len(self.format_time):\n                self.active_time_format = 0\n            # save the active format_time\n            time_format = self.format_time[self.active_time_format]\n            self.py3.storage_set(\"time_format\", time_format)\n        elif event[\"button\"] == self.button_change_format:\n            self._change_active(1)\n\n    def clock(self):\n\n        # cycling\n        if self.cycle and time.time() >= self._cycle_time:\n            self._change_active(1)\n            self._cycle_time = time.time() + self.cycle\n\n        # update our times\n        times = {}\n        for name in self._fmts:\n            zone = self._get_timezone(name)\n            if zone == \"?\":\n                times[name] = \"?\"\n            else:\n                t = datetime.now(zone)\n                format_time = self.format_time[self.active_time_format]\n                icon = None\n                if self.py3.format_contains(format_time, \"icon\"):\n                    # calculate the decimal hour\n                    h = t.hour + t.minute / 60\n                    if self.round_to_nearest_block:\n                        h += self.block_hours / len(self.blocks) / 2\n                    # make 12 hourly etc\n                    h = h % self.block_hours\n                    idx = int(h / self.block_hours * len(self.blocks))\n                    icon = self.blocks[idx]\n\n                try:\n                    # tzlocal < 3.0\n                    timezone = zone.zone\n                except AttributeError:\n                    # tzlocal >= 3.0\n                    timezone = zone.key\n                tzname = timezone.split(\"/\")[-1].replace(\"_\", \" \")\n\n                if self.multiple_tz:\n                    name_unclear = tzname\n                    timezone_unclear = timezone\n                else:\n                    name_unclear = \"\"\n                    timezone_unclear = \"\"\n\n                format_time = self.py3.safe_format(\n                    format_time,\n                    dict(\n                        icon=icon,\n                        name=tzname,\n                        name_unclear=name_unclear,\n                        timezone=timezone,\n                        timezone_unclear=timezone_unclear,\n                    ),\n                )\n\n                if self.py3.is_composite(format_time):\n                    for item in format_time:\n                        item[\"full_text\"] = t.strftime(item[\"full_text\"])\n                else:\n                    format_time = t.strftime(format_time)\n                times[name] = format_time\n\n        # work out when we need to update\n        timeout = self.py3.time_in(sync_to=self.time_deltas[self.active_time_format])\n\n        # if cycling we need to make sure we update when they are needed\n        if self.cycle:\n            cycle_timeout = self._cycle_time\n            timeout = min(timeout, cycle_timeout)\n\n        return {\n            \"full_text\": self.py3.safe_format(self.format[self.active], times),\n            \"cached_until\": timeout,\n        }\n\n\nif __name__ == \"__main__\":\n    \"\"\"\n    Run module in test mode.\n    \"\"\"\n    from py3status.module_test import module_test\n\n    module_test(Py3status)\n", "path": "py3status/modules/clock.py"}], "after_files": [{"content": "\"\"\"\nDisplay date and time.\n\nThis module allows one or more datetimes to be displayed.\nAll datetimes share the same format_time but can set their own timezones.\nTimezones are defined in the `format` using the TZ name in squiggly brackets eg\n`{GMT}`, `{Portugal}`, `{Europe/Paris}`, `{America/Argentina/Buenos_Aires}`.\n\nSee https://docs.python.org/3/library/zoneinfo.html for supported formats.\n\n`{Local}` can be used for the local settings of your computer.\n\nNote: Timezones are case sensitive!\n\nA full list of timezones can be found at\nhttps://en.wikipedia.org/wiki/List_of_tz_database_time_zones\n\nConfiguration parameters:\n    block_hours: length of time period for all blocks in hours (default 12)\n    blocks: a string, where each character represents time period\n        from the start of a time period.\n        (default '\ud83d\udd5b\ud83d\udd67\ud83d\udd50\ud83d\udd5c\ud83d\udd51\ud83d\udd5d\ud83d\udd52\ud83d\udd5e\ud83d\udd53\ud83d\udd5f\ud83d\udd54\ud83d\udd60\ud83d\udd55\ud83d\udd61\ud83d\udd56\ud83d\udd62\ud83d\udd57\ud83d\udd63\ud83d\udd58\ud83d\udd64\ud83d\udd59\ud83d\udd65\ud83d\udd5a\ud83d\udd66')\n    button_change_format: button that switches format used setting to None\n        disables (default 1)\n    button_change_time_format: button that switches format_time used. Setting\n        to None disables (default 2)\n    button_reset: button that switches display to the first timezone. Setting\n        to None disables (default 3)\n    cycle: If more than one display then how many seconds between changing the\n        display (default 0)\n    format: defines the timezones displayed. This can be a single string or a\n        list.  If a list is supplied then the formats can be cycled through\n        using `cycle` or by button click.  (default '{Local}')\n    format_time: format to use for the time, strftime directives such as `%H`\n        can be used this can be either a string or to allow multiple formats as\n        a list.  The one used can be changed by button click.\n        *(default ['[{name_unclear} ]%c', '[{name_unclear} ]%x %X',\n        '[{name_unclear} ]%a %H:%M', '[{name_unclear} ]{icon}'])*\n    locale: Override the system locale. Examples:\n        when set to 'fr_FR' %a on Tuesday is 'mar.'.\n        (default None)\n    round_to_nearest_block: defines how a block icon is chosen. Examples:\n        when set to True,  '13:14' is '\ud83d\udd50', '13:16' is '\ud83d\udd5c' and '13:31' is '\ud83d\udd5c';\n        when set to False, '13:14' is '\ud83d\udd50', '13:16' is '\ud83d\udd50' and '13:31' is '\ud83d\udd5c'.\n        (default True)\n\nFormat placeholders:\n    {icon} a character representing the time from `blocks`\n    {name} friendly timezone name eg `Buenos Aires`\n    {name_unclear} friendly timezone name eg `Buenos Aires` but is empty if\n        only one timezone is provided\n    {timezone} full timezone name eg `America/Argentina/Buenos_Aires`\n    {timezone_unclear} full timezone name eg `America/Argentina/Buenos_Aires`\n        but is empty if only one timezone is provided\n\nExamples:\n```\n# cycling through London, Warsaw, Tokyo\nclock {\n    cycle = 30\n    format = [\"{Europe/London}\", \"{Europe/Warsaw}\", \"{Asia/Tokyo}\"]\n    format_time = \"{name} %H:%M\"\n}\n\n# Show the time and date in New York\nclock {\n   format = \"Big Apple {America/New_York}\"\n   format_time = \"%Y-%m-%d %H:%M:%S\"\n}\n\n# wall clocks\nclock {\n    format = \"{Asia/Calcutta} {Africa/Nairobi} {Asia/Bangkok}\"\n    format_time = \"{name} {icon}\"\n}\n```\n\n@author tobes ultrabug\n@license BSD\n\nSAMPLE OUTPUT\n{'full_text': 'Sun 15 Jan 2017 23:27:17 GMT'}\n\nlondon\n{'full_text': 'Thursday Feb 23 1:42 AM London'}\n\"\"\"\n\nimport locale\nimport re\nimport time\nfrom datetime import datetime\n\ntry:\n    import zoneinfo\n# Fall back for python 3.7 and python 3.8\nexcept ImportError:\n    from backports import zoneinfo\n\nCLOCK_BLOCKS = \"\ud83d\udd5b\ud83d\udd67\ud83d\udd50\ud83d\udd5c\ud83d\udd51\ud83d\udd5d\ud83d\udd52\ud83d\udd5e\ud83d\udd53\ud83d\udd5f\ud83d\udd54\ud83d\udd60\ud83d\udd55\ud83d\udd61\ud83d\udd56\ud83d\udd62\ud83d\udd57\ud83d\udd63\ud83d\udd58\ud83d\udd64\ud83d\udd59\ud83d\udd65\ud83d\udd5a\ud83d\udd66\"\n\n\nclass Py3status:\n    \"\"\" \"\"\"\n\n    # available configuration parameters\n    block_hours = 12\n    blocks = CLOCK_BLOCKS\n    button_change_format = 1\n    button_change_time_format = 2\n    button_reset = 3\n    cycle = 0\n    format = \"{Local}\"\n    format_time = [\n        \"[{name_unclear} ]%c\",\n        \"[{name_unclear} ]%x %X\",\n        \"[{name_unclear} ]%a %H:%M\",\n        \"[{name_unclear} ]{icon}\",\n    ]\n    locale = None\n    round_to_nearest_block = True\n\n    def post_config_hook(self):\n        if self.locale is not None:\n            locale.setlocale(locale.LC_TIME, self.locale)\n\n        # Multiple clocks are possible that can be cycled through\n        if not isinstance(self.format, list):\n            self.format = [self.format]\n        # if only one item we don't need to cycle\n        if len(self.format) == 1:\n            self.cycle = 0\n        # find any declared timezones eg {Europe/London}\n        self._fmts = set()\n        for fmt in self.format:\n            self._fmts.update(self.py3.get_placeholders_list(fmt))\n\n        self.multiple_tz = len(self._fmts) > 1\n\n        if not isinstance(self.format_time, list):\n            self.format_time = [self.format_time]\n\n        # workout how often in seconds we will need to do an update to keep the\n        # display fresh\n        self.time_deltas = []\n        for format in self.format_time:\n            format_time = re.sub(r\"{([^}]*)}\", \"\", format)\n            format_time = format_time.replace(\"%%\", \"\")\n            if \"%f\" in format_time:\n                # microseconds\n                time_delta = 0\n            elif \"%S\" in format_time:\n                # seconds\n                time_delta = 1\n            elif \"%s\" in format_time:\n                # seconds since unix epoch start\n                time_delta = 1\n            elif \"%T\" in format_time:\n                # seconds included in \"%H:%M:%S\"\n                time_delta = 1\n            elif \"%c\" in format_time:\n                # Locale\u2019s appropriate date and time representation\n                time_delta = 1\n            elif \"%X\" in format_time:\n                # Locale\u2019s appropriate time representation\n                time_delta = 1\n            else:\n                time_delta = 60\n            self.time_deltas.append(time_delta)\n\n        # If we have saved details we use them.\n        saved_format = self.py3.storage_get(\"time_format\")\n        if saved_format in self.format_time:\n            self.active_time_format = self.format_time.index(saved_format)\n        else:\n            self.active_time_format = 0\n\n        saved_timezone = self.py3.storage_get(\"timezone\")\n        if saved_timezone in self.format:\n            self.active = self.format.index(saved_timezone)\n        else:\n            self.active = 0\n\n        # reset the cycle time\n        self._cycle_time = time.time() + self.cycle\n\n    def _get_timezone(self, tz):\n        \"\"\"\n        Find and return the time zone if possible\n        \"\"\"\n        # special Local timezone\n        if tz == \"Local\":\n            try:\n                return zoneinfo.ZoneInfo(\"localtime\")\n            except zoneinfo.ZoneInfoNotFoundError:\n                return \"?\"\n        # get the timezone\n        try:\n            zone = zoneinfo.ZoneInfo(tz)\n        except zoneinfo.ZoneInfoNotFoundError:\n            return \"?\"\n        return zone\n\n    def _change_active(self, diff):\n        self.active = (self.active + diff) % len(self.format)\n        # reset the cycle time\n        self._cycle_time = time.time() + self.cycle\n        # save the active format\n        timezone = self.format[self.active]\n        self.py3.storage_set(\"timezone\", timezone)\n\n    def on_click(self, event):\n        \"\"\"\n        Switch the displayed module or pass the event on to the active module\n        \"\"\"\n        if event[\"button\"] == self.button_reset:\n            self._change_active(0)\n        elif event[\"button\"] == self.button_change_time_format:\n            self.active_time_format += 1\n            if self.active_time_format >= len(self.format_time):\n                self.active_time_format = 0\n            # save the active format_time\n            time_format = self.format_time[self.active_time_format]\n            self.py3.storage_set(\"time_format\", time_format)\n        elif event[\"button\"] == self.button_change_format:\n            self._change_active(1)\n\n    def clock(self):\n\n        # cycling\n        if self.cycle and time.time() >= self._cycle_time:\n            self._change_active(1)\n            self._cycle_time = time.time() + self.cycle\n\n        # update our times\n        times = {}\n        for name in self._fmts:\n            zone = self._get_timezone(name)\n            if zone == \"?\":\n                times[name] = \"?\"\n            else:\n                t = datetime.now(zone)\n                format_time = self.format_time[self.active_time_format]\n                icon = None\n                if self.py3.format_contains(format_time, \"icon\"):\n                    # calculate the decimal hour\n                    h = t.hour + t.minute / 60\n                    if self.round_to_nearest_block:\n                        h += self.block_hours / len(self.blocks) / 2\n                    # make 12 hourly etc\n                    h = h % self.block_hours\n                    idx = int(h / self.block_hours * len(self.blocks))\n                    icon = self.blocks[idx]\n\n                timezone = zone.key\n                tzname = timezone.split(\"/\")[-1].replace(\"_\", \" \")\n\n                if self.multiple_tz:\n                    name_unclear = tzname\n                    timezone_unclear = timezone\n                else:\n                    name_unclear = \"\"\n                    timezone_unclear = \"\"\n\n                format_time = self.py3.safe_format(\n                    format_time,\n                    dict(\n                        icon=icon,\n                        name=tzname,\n                        name_unclear=name_unclear,\n                        timezone=timezone,\n                        timezone_unclear=timezone_unclear,\n                    ),\n                )\n\n                if self.py3.is_composite(format_time):\n                    for item in format_time:\n                        item[\"full_text\"] = t.strftime(item[\"full_text\"])\n                else:\n                    format_time = t.strftime(format_time)\n                times[name] = format_time\n\n        # work out when we need to update\n        timeout = self.py3.time_in(sync_to=self.time_deltas[self.active_time_format])\n\n        # if cycling we need to make sure we update when they are needed\n        if self.cycle:\n            cycle_timeout = self._cycle_time\n            timeout = min(timeout, cycle_timeout)\n\n        return {\n            \"full_text\": self.py3.safe_format(self.format[self.active], times),\n            \"cached_until\": timeout,\n        }\n\n\nif __name__ == \"__main__\":\n    \"\"\"\n    Run module in test mode.\n    \"\"\"\n    from py3status.module_test import module_test\n\n    module_test(Py3status)\n", "path": "py3status/modules/clock.py"}]}