clox 0.7__tar.gz → 0.9__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of clox might be problematic. Click here for more details.

@@ -5,6 +5,22 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
5
5
  and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6
6
 
7
7
  ## [Unreleased]
8
+ ## [0.9] - 2025-04-14
9
+ ### Added
10
+ - Timezone difference
11
+ ### Changed
12
+ - Python typing features added to all modules
13
+ - Test system modified
14
+ - `Python 3.6` support dropped
15
+ ## [0.8] - 2025-03-16
16
+ ### Added
17
+ - `--country` argument
18
+ - `--countries-list` argument
19
+ - `COUNTRIES.md`
20
+ ### Changed
21
+ - Input case sensitivity bug fixed
22
+ - Test system modified
23
+ - `README.md` updated
8
24
  ## [0.7] - 2025-03-06
9
25
  ### Added
10
26
  - Jalali calendar
@@ -49,7 +65,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
49
65
  - `TIMEZONES.md`
50
66
  - `FACES.md`
51
67
 
52
- [Unreleased]: https://github.com/sepandhaghighi/clox/compare/v0.7...dev
68
+ [Unreleased]: https://github.com/sepandhaghighi/clox/compare/v0.9...dev
69
+ [0.9]: https://github.com/sepandhaghighi/clox/compare/v0.8...v0.9
70
+ [0.8]: https://github.com/sepandhaghighi/clox/compare/v0.7...v0.8
53
71
  [0.7]: https://github.com/sepandhaghighi/clox/compare/v0.6...v0.7
54
72
  [0.6]: https://github.com/sepandhaghighi/clox/compare/v0.5...v0.6
55
73
  [0.5]: https://github.com/sepandhaghighi/clox/compare/v0.4...v0.5
clox-0.9/COUNTRIES.md ADDED
@@ -0,0 +1,252 @@
1
+ # Countries List
2
+
3
+ **Last Update: 2025-03-11**
4
+
5
+
6
+ 1. AD - Andorra
7
+ 2. AE - United Arab Emirates
8
+ 3. AF - Afghanistan
9
+ 4. AG - Antigua & Barbuda
10
+ 5. AI - Anguilla
11
+ 6. AL - Albania
12
+ 7. AM - Armenia
13
+ 8. AO - Angola
14
+ 9. AQ - Antarctica
15
+ 10. AR - Argentina
16
+ 11. AS - Samoa (American)
17
+ 12. AT - Austria
18
+ 13. AU - Australia
19
+ 14. AW - Aruba
20
+ 15. AX - Åland Islands
21
+ 16. AZ - Azerbaijan
22
+ 17. BA - Bosnia & Herzegovina
23
+ 18. BB - Barbados
24
+ 19. BD - Bangladesh
25
+ 20. BE - Belgium
26
+ 21. BF - Burkina Faso
27
+ 22. BG - Bulgaria
28
+ 23. BH - Bahrain
29
+ 24. BI - Burundi
30
+ 25. BJ - Benin
31
+ 26. BL - St Barthelemy
32
+ 27. BM - Bermuda
33
+ 28. BN - Brunei
34
+ 29. BO - Bolivia
35
+ 30. BQ - Caribbean NL
36
+ 31. BR - Brazil
37
+ 32. BS - Bahamas
38
+ 33. BT - Bhutan
39
+ 34. BW - Botswana
40
+ 35. BY - Belarus
41
+ 36. BZ - Belize
42
+ 37. CA - Canada
43
+ 38. CC - Cocos (Keeling) Islands
44
+ 39. CD - Congo (Dem. Rep.)
45
+ 40. CF - Central African Rep.
46
+ 41. CG - Congo (Rep.)
47
+ 42. CH - Switzerland
48
+ 43. CI - Côte d'Ivoire
49
+ 44. CK - Cook Islands
50
+ 45. CL - Chile
51
+ 46. CM - Cameroon
52
+ 47. CN - China
53
+ 48. CO - Colombia
54
+ 49. CR - Costa Rica
55
+ 50. CU - Cuba
56
+ 51. CV - Cape Verde
57
+ 52. CW - Curaçao
58
+ 53. CX - Christmas Island
59
+ 54. CY - Cyprus
60
+ 55. CZ - Czech Republic
61
+ 56. DE - Germany
62
+ 57. DJ - Djibouti
63
+ 58. DK - Denmark
64
+ 59. DM - Dominica
65
+ 60. DO - Dominican Republic
66
+ 61. DZ - Algeria
67
+ 62. EC - Ecuador
68
+ 63. EE - Estonia
69
+ 64. EG - Egypt
70
+ 65. EH - Western Sahara
71
+ 66. ER - Eritrea
72
+ 67. ES - Spain
73
+ 68. ET - Ethiopia
74
+ 69. FI - Finland
75
+ 70. FJ - Fiji
76
+ 71. FK - Falkland Islands
77
+ 72. FM - Micronesia
78
+ 73. FO - Faroe Islands
79
+ 74. FR - France
80
+ 75. GA - Gabon
81
+ 76. GB - Britain (UK)
82
+ 77. GD - Grenada
83
+ 78. GE - Georgia
84
+ 79. GF - French Guiana
85
+ 80. GG - Guernsey
86
+ 81. GH - Ghana
87
+ 82. GI - Gibraltar
88
+ 83. GL - Greenland
89
+ 84. GM - Gambia
90
+ 85. GN - Guinea
91
+ 86. GP - Guadeloupe
92
+ 87. GQ - Equatorial Guinea
93
+ 88. GR - Greece
94
+ 89. GS - South Georgia & the South Sandwich Islands
95
+ 90. GT - Guatemala
96
+ 91. GU - Guam
97
+ 92. GW - Guinea-Bissau
98
+ 93. GY - Guyana
99
+ 94. HK - Hong Kong
100
+ 95. HN - Honduras
101
+ 96. HR - Croatia
102
+ 97. HT - Haiti
103
+ 98. HU - Hungary
104
+ 99. ID - Indonesia
105
+ 100. IE - Ireland
106
+ 101. IL - Israel
107
+ 102. IM - Isle of Man
108
+ 103. IN - India
109
+ 104. IO - British Indian Ocean Territory
110
+ 105. IQ - Iraq
111
+ 106. IR - Iran
112
+ 107. IS - Iceland
113
+ 108. IT - Italy
114
+ 109. JE - Jersey
115
+ 110. JM - Jamaica
116
+ 111. JO - Jordan
117
+ 112. JP - Japan
118
+ 113. KE - Kenya
119
+ 114. KG - Kyrgyzstan
120
+ 115. KH - Cambodia
121
+ 116. KI - Kiribati
122
+ 117. KM - Comoros
123
+ 118. KN - St Kitts & Nevis
124
+ 119. KP - Korea (North)
125
+ 120. KR - Korea (South)
126
+ 121. KW - Kuwait
127
+ 122. KY - Cayman Islands
128
+ 123. KZ - Kazakhstan
129
+ 124. LA - Laos
130
+ 125. LB - Lebanon
131
+ 126. LC - St Lucia
132
+ 127. LI - Liechtenstein
133
+ 128. LK - Sri Lanka
134
+ 129. LR - Liberia
135
+ 130. LS - Lesotho
136
+ 131. LT - Lithuania
137
+ 132. LU - Luxembourg
138
+ 133. LV - Latvia
139
+ 134. LY - Libya
140
+ 135. MA - Morocco
141
+ 136. MC - Monaco
142
+ 137. MD - Moldova
143
+ 138. ME - Montenegro
144
+ 139. MF - St Martin (French)
145
+ 140. MG - Madagascar
146
+ 141. MH - Marshall Islands
147
+ 142. MK - North Macedonia
148
+ 143. ML - Mali
149
+ 144. MM - Myanmar (Burma)
150
+ 145. MN - Mongolia
151
+ 146. MO - Macau
152
+ 147. MP - Northern Mariana Islands
153
+ 148. MQ - Martinique
154
+ 149. MR - Mauritania
155
+ 150. MS - Montserrat
156
+ 151. MT - Malta
157
+ 152. MU - Mauritius
158
+ 153. MV - Maldives
159
+ 154. MW - Malawi
160
+ 155. MX - Mexico
161
+ 156. MY - Malaysia
162
+ 157. MZ - Mozambique
163
+ 158. NA - Namibia
164
+ 159. NC - New Caledonia
165
+ 160. NE - Niger
166
+ 161. NF - Norfolk Island
167
+ 162. NG - Nigeria
168
+ 163. NI - Nicaragua
169
+ 164. NL - Netherlands
170
+ 165. NO - Norway
171
+ 166. NP - Nepal
172
+ 167. NR - Nauru
173
+ 168. NU - Niue
174
+ 169. NZ - New Zealand
175
+ 170. OM - Oman
176
+ 171. PA - Panama
177
+ 172. PE - Peru
178
+ 173. PF - French Polynesia
179
+ 174. PG - Papua New Guinea
180
+ 175. PH - Philippines
181
+ 176. PK - Pakistan
182
+ 177. PL - Poland
183
+ 178. PM - St Pierre & Miquelon
184
+ 179. PN - Pitcairn
185
+ 180. PR - Puerto Rico
186
+ 181. PS - Palestine
187
+ 182. PT - Portugal
188
+ 183. PW - Palau
189
+ 184. PY - Paraguay
190
+ 185. QA - Qatar
191
+ 186. RE - Réunion
192
+ 187. RO - Romania
193
+ 188. RS - Serbia
194
+ 189. RU - Russia
195
+ 190. RW - Rwanda
196
+ 191. SA - Saudi Arabia
197
+ 192. SB - Solomon Islands
198
+ 193. SC - Seychelles
199
+ 194. SD - Sudan
200
+ 195. SE - Sweden
201
+ 196. SG - Singapore
202
+ 197. SH - St Helena
203
+ 198. SI - Slovenia
204
+ 199. SJ - Svalbard & Jan Mayen
205
+ 200. SK - Slovakia
206
+ 201. SL - Sierra Leone
207
+ 202. SM - San Marino
208
+ 203. SN - Senegal
209
+ 204. SO - Somalia
210
+ 205. SR - Suriname
211
+ 206. SS - South Sudan
212
+ 207. ST - Sao Tome & Principe
213
+ 208. SV - El Salvador
214
+ 209. SX - St Maarten (Dutch)
215
+ 210. SY - Syria
216
+ 211. SZ - Eswatini (Swaziland)
217
+ 212. TC - Turks & Caicos Is
218
+ 213. TD - Chad
219
+ 214. TF - French Southern & Antarctic Lands
220
+ 215. TG - Togo
221
+ 216. TH - Thailand
222
+ 217. TJ - Tajikistan
223
+ 218. TK - Tokelau
224
+ 219. TL - East Timor
225
+ 220. TM - Turkmenistan
226
+ 221. TN - Tunisia
227
+ 222. TO - Tonga
228
+ 223. TR - Turkey
229
+ 224. TT - Trinidad & Tobago
230
+ 225. TV - Tuvalu
231
+ 226. TW - Taiwan
232
+ 227. TZ - Tanzania
233
+ 228. UA - Ukraine
234
+ 229. UG - Uganda
235
+ 230. UM - US minor outlying islands
236
+ 231. US - United States
237
+ 232. UY - Uruguay
238
+ 233. UZ - Uzbekistan
239
+ 234. VA - Vatican City
240
+ 235. VC - St Vincent
241
+ 236. VE - Venezuela
242
+ 237. VG - Virgin Islands (UK)
243
+ 238. VI - Virgin Islands (US)
244
+ 239. VN - Vietnam
245
+ 240. VU - Vanuatu
246
+ 241. WF - Wallis & Futuna
247
+ 242. WS - Samoa (western)
248
+ 243. YE - Yemen
249
+ 244. YT - Mayotte
250
+ 245. ZA - South Africa
251
+ 246. ZM - Zambia
252
+ 247. ZW - Zimbabwe
@@ -1,9 +1,9 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: clox
3
- Version: 0.7
3
+ Version: 0.9
4
4
  Summary: A Geeky Clock for Terminal Enthusiasts
5
5
  Home-page: https://github.com/sepandhaghighi/clox
6
- Download-URL: https://github.com/sepandhaghighi/clox/tarball/v0.7
6
+ Download-URL: https://github.com/sepandhaghighi/clox/tarball/v0.9
7
7
  Author: Sepand Haghighi
8
8
  Author-email: me@sepand.tech
9
9
  License: MIT
@@ -13,7 +13,6 @@ Classifier: Development Status :: 4 - Beta
13
13
  Classifier: Natural Language :: English
14
14
  Classifier: License :: OSI Approved :: MIT License
15
15
  Classifier: Operating System :: OS Independent
16
- Classifier: Programming Language :: Python :: 3.6
17
16
  Classifier: Programming Language :: Python :: 3.7
18
17
  Classifier: Programming Language :: Python :: 3.8
19
18
  Classifier: Programming Language :: Python :: 3.9
@@ -27,7 +26,7 @@ Classifier: Intended Audience :: End Users/Desktop
27
26
  Classifier: Intended Audience :: Other Audience
28
27
  Classifier: Topic :: Games/Entertainment
29
28
  Classifier: Topic :: Utilities
30
- Requires-Python: >=3.6
29
+ Requires-Python: >=3.7
31
30
  Description-Content-Type: text/markdown
32
31
  License-File: LICENSE
33
32
  License-File: AUTHORS.md
@@ -43,6 +42,7 @@ Dynamic: download-url
43
42
  Dynamic: home-page
44
43
  Dynamic: keywords
45
44
  Dynamic: license
45
+ Dynamic: license-file
46
46
  Dynamic: project-url
47
47
  Dynamic: requires-dist
48
48
  Dynamic: requires-python
@@ -104,13 +104,13 @@ Clox is a terminal-based clock application designed for terminal enthusiasts who
104
104
  ## Installation
105
105
 
106
106
  ### Source Code
107
- - Download [Version 0.7](https://github.com/sepandhaghighi/clox/archive/v0.7.zip) or [Latest Source](https://github.com/sepandhaghighi/clox/archive/dev.zip)
107
+ - Download [Version 0.9](https://github.com/sepandhaghighi/clox/archive/v0.9.zip) or [Latest Source](https://github.com/sepandhaghighi/clox/archive/dev.zip)
108
108
  - `pip install .`
109
109
 
110
110
  ### PyPI
111
111
 
112
112
  - Check [Python Packaging User Guide](https://packaging.python.org/installing/)
113
- - `pip install clox==0.7`
113
+ - `pip install clox==0.9`
114
114
 
115
115
 
116
116
  ## Usage
@@ -143,16 +143,30 @@ clox
143
143
  clox --face=3
144
144
  ```
145
145
  * Use `--face=-1` for random mode
146
- * [Faces List](https://github.com/sepandhaghighi/clox/blob/main/FACES.md)
147
- * `clox --faces-list`
146
+ * [Faces List](https://github.com/sepandhaghighi/clox/blob/main/FACES.md): `clox --faces-list`
147
+
148
148
 
149
149
  ### Timezone
150
150
 
151
151
  ```console
152
152
  clox --timezone="Etc/GMT+7"
153
153
  ```
154
- * [Timezones List](https://github.com/sepandhaghighi/clox/blob/main/TIMEZONES.md)
155
- * `clox --timezones-list`
154
+ * [Timezones List](https://github.com/sepandhaghighi/clox/blob/main/TIMEZONES.md): `clox --timezones-list`
155
+
156
+
157
+ ### Country
158
+
159
+ The `--country` argument allows you to specify a country using its **ISO 3166** code format
160
+
161
+ ℹ️ When the `--country` argument is provided, the `--timezone` argument will be ignored
162
+
163
+ ℹ️ If the specified country has multiple timezones, the first timezone will be selected automatically
164
+
165
+ ```console
166
+ clox --country="DE"
167
+ ```
168
+ * [Countries List](https://github.com/sepandhaghighi/clox/blob/main/COUNTRIES.md): `clox --countries-list`
169
+
156
170
 
157
171
  ### Vertical/Horizontal Shift
158
172
 
@@ -278,6 +292,22 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
278
292
  and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
279
293
 
280
294
  ## [Unreleased]
295
+ ## [0.9] - 2025-04-14
296
+ ### Added
297
+ - Timezone difference
298
+ ### Changed
299
+ - Python typing features added to all modules
300
+ - Test system modified
301
+ - `Python 3.6` support dropped
302
+ ## [0.8] - 2025-03-16
303
+ ### Added
304
+ - `--country` argument
305
+ - `--countries-list` argument
306
+ - `COUNTRIES.md`
307
+ ### Changed
308
+ - Input case sensitivity bug fixed
309
+ - Test system modified
310
+ - `README.md` updated
281
311
  ## [0.7] - 2025-03-06
282
312
  ### Added
283
313
  - Jalali calendar
@@ -322,7 +352,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
322
352
  - `TIMEZONES.md`
323
353
  - `FACES.md`
324
354
 
325
- [Unreleased]: https://github.com/sepandhaghighi/clox/compare/v0.7...dev
355
+ [Unreleased]: https://github.com/sepandhaghighi/clox/compare/v0.9...dev
356
+ [0.9]: https://github.com/sepandhaghighi/clox/compare/v0.8...v0.9
357
+ [0.8]: https://github.com/sepandhaghighi/clox/compare/v0.7...v0.8
326
358
  [0.7]: https://github.com/sepandhaghighi/clox/compare/v0.6...v0.7
327
359
  [0.6]: https://github.com/sepandhaghighi/clox/compare/v0.5...v0.6
328
360
  [0.5]: https://github.com/sepandhaghighi/clox/compare/v0.4...v0.5
@@ -53,13 +53,13 @@ Clox is a terminal-based clock application designed for terminal enthusiasts who
53
53
  ## Installation
54
54
 
55
55
  ### Source Code
56
- - Download [Version 0.7](https://github.com/sepandhaghighi/clox/archive/v0.7.zip) or [Latest Source](https://github.com/sepandhaghighi/clox/archive/dev.zip)
56
+ - Download [Version 0.9](https://github.com/sepandhaghighi/clox/archive/v0.9.zip) or [Latest Source](https://github.com/sepandhaghighi/clox/archive/dev.zip)
57
57
  - `pip install .`
58
58
 
59
59
  ### PyPI
60
60
 
61
61
  - Check [Python Packaging User Guide](https://packaging.python.org/installing/)
62
- - `pip install clox==0.7`
62
+ - `pip install clox==0.9`
63
63
 
64
64
 
65
65
  ## Usage
@@ -92,16 +92,30 @@ clox
92
92
  clox --face=3
93
93
  ```
94
94
  * Use `--face=-1` for random mode
95
- * [Faces List](https://github.com/sepandhaghighi/clox/blob/main/FACES.md)
96
- * `clox --faces-list`
95
+ * [Faces List](https://github.com/sepandhaghighi/clox/blob/main/FACES.md): `clox --faces-list`
96
+
97
97
 
98
98
  ### Timezone
99
99
 
100
100
  ```console
101
101
  clox --timezone="Etc/GMT+7"
102
102
  ```
103
- * [Timezones List](https://github.com/sepandhaghighi/clox/blob/main/TIMEZONES.md)
104
- * `clox --timezones-list`
103
+ * [Timezones List](https://github.com/sepandhaghighi/clox/blob/main/TIMEZONES.md): `clox --timezones-list`
104
+
105
+
106
+ ### Country
107
+
108
+ The `--country` argument allows you to specify a country using its **ISO 3166** code format
109
+
110
+ ℹ️ When the `--country` argument is provided, the `--timezone` argument will be ignored
111
+
112
+ ℹ️ If the specified country has multiple timezones, the first timezone will be selected automatically
113
+
114
+ ```console
115
+ clox --country="DE"
116
+ ```
117
+ * [Countries List](https://github.com/sepandhaghighi/clox/blob/main/COUNTRIES.md): `clox --countries-list`
118
+
105
119
 
106
120
  ### Vertical/Horizontal Shift
107
121
 
@@ -4,8 +4,8 @@
4
4
 
5
5
  | Version | Supported |
6
6
  | ------------- | ------------------ |
7
- | 0.7 | :white_check_mark: |
8
- | < 0.7 | :x: |
7
+ | 0.9 | :white_check_mark: |
8
+ | < 0.9 | :x: |
9
9
 
10
10
  ## Reporting a Vulnerability
11
11
 
@@ -1,5 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  """clox functions."""
3
+ from typing import Optional
3
4
  import os
4
5
  import sys
5
6
  import time
@@ -13,57 +14,72 @@ from art import tprint
13
14
  from .jcalendar import TextCalendar as JalaliCalendar
14
15
  from .params import HORIZONTAL_TIME_24H_FORMATS, VERTICAL_TIME_24H_FORMATS
15
16
  from .params import HORIZONTAL_TIME_12H_FORMATS, VERTICAL_TIME_12H_FORMATS
16
- from .params import TIMEZONES_LIST, CLOX_VERSION, DATE_FORMAT
17
+ from .params import TIMEZONE_DIFFERENCE_FORMAT
18
+ from .params import CLOX_VERSION, DATE_FORMAT
19
+ from .params import TIMEZONES_LIST, COUNTRIES_LIST
17
20
  from .params import ADDITIONAL_INFO, EXIT_MESSAGE
18
- from .params import FACES_MAP, FACES_LIST, CALENDAR_LIST, DATE_SYSTEMS_LIST
21
+ from .params import FACES_MAP, FACES_LIST, CALENDARS_LIST, DATE_SYSTEMS_LIST
19
22
  from .params import HORIZONTAL_FACES_LIST_EXAMPLE, VERTICAL_FACES_LIST_EXAMPLE
20
23
  from .params import CLOX_OVERVIEW, CLOX_REPO
21
24
 
22
25
 
23
- def clox_info():
24
- """
25
- Print clox details.
26
-
27
- :return: None
28
- """
26
+ def clox_info() -> None:
27
+ """Print clox details."""
29
28
  tprint("Clox")
30
29
  tprint("V:" + CLOX_VERSION)
31
30
  print(CLOX_OVERVIEW)
32
31
  print(CLOX_REPO)
33
32
 
34
33
 
35
- def clear_screen():
36
- """
37
- Clear screen function.
38
-
39
- :return: None
40
- """
34
+ def clear_screen() -> None:
35
+ """Clear screen function."""
41
36
  if sys.platform == "win32":
42
37
  os.system('cls')
43
38
  else:
44
39
  os.system('clear')
45
40
 
46
41
 
47
- def get_face(index):
42
+ def get_face(index: int) -> str:
48
43
  """
49
44
  Return face name.
50
45
 
51
46
  :param index: face index
52
- :type index: int
53
- :return: face name as str
54
47
  """
55
48
  if index == -1:
56
49
  index = random.choice(sorted(FACES_MAP))
57
50
  return FACES_MAP[index]
58
51
 
59
52
 
60
- def show_faces_list(vertical=False):
53
+ def get_timezone_difference(timezone: str) -> str:
54
+ """
55
+ Return timezone difference.
56
+
57
+ :param timezone: timezone
58
+ """
59
+ direction = "ahead"
60
+ tz = pytz.timezone(timezone)
61
+ datetime_now_timezone = datetime.datetime.now(tz=tz)
62
+ datetime_now_local = datetime.datetime.now()
63
+ difference = datetime_now_timezone - tz.localize(datetime_now_local)
64
+ total_minutes = difference.total_seconds() // 60
65
+ if total_minutes < 0:
66
+ direction = "behind"
67
+ total_minutes = abs(total_minutes)
68
+ if total_minutes == 0:
69
+ direction = "same"
70
+ hours = total_minutes // 60
71
+ minutes = total_minutes % 60
72
+ minutes = round(minutes / 15) * 15
73
+ formatted_difference = TIMEZONE_DIFFERENCE_FORMAT.format(
74
+ hours=int(hours), minutes=int(minutes), direction=direction)
75
+ return formatted_difference
76
+
77
+
78
+ def show_faces_list(vertical: bool = False) -> None:
61
79
  """
62
80
  Show faces list.
63
81
 
64
82
  :param vertical: vertical mode flag
65
- :type vertical: bool
66
- :return: None
67
83
  """
68
84
  mode = "Horizontal"
69
85
  example = HORIZONTAL_FACES_LIST_EXAMPLE
@@ -77,32 +93,54 @@ def show_faces_list(vertical=False):
77
93
  print('=' * 80)
78
94
 
79
95
 
80
- def show_timezones_list():
96
+ def show_timezones_list(country: Optional[str] = None) -> None:
81
97
  """
82
98
  Show timezones list.
83
99
 
84
- :return: None
100
+ :param country: country iso3166 code
85
101
  """
86
- print("Timezones list:\n")
87
- for index, timezone in enumerate(TIMEZONES_LIST, 1):
102
+ timezones_list = TIMEZONES_LIST
103
+ country_name = "All"
104
+ if country is not None:
105
+ timezones_list = list(map(lambda x: x.upper(), pytz.country_timezones(country)))
106
+ country_name = pytz.country_names[country]
107
+ try:
108
+ print("Timezones list ({country_name}):\n".format(country_name=country_name))
109
+ except Exception:
110
+ print("Timezones list ({country_name}):\n".format(country_name=country.upper()))
111
+ for index, timezone in enumerate(sorted(timezones_list), 1):
88
112
  print("{index}. {timezone}".format(index=index, timezone=timezone))
89
113
 
90
114
 
91
- def print_calendar(mode="month", timezone=None, v_shift=0, h_shift=0, date_system="gregorian"):
115
+ def show_countries_list() -> None:
116
+ """Show countries list."""
117
+ print("Countries list:\n")
118
+ for index, country_code in enumerate(sorted(COUNTRIES_LIST), 1):
119
+ country_name = pytz.country_names[country_code]
120
+ try:
121
+ print("{index}. {country_code} - {country_name}".format(index=index,
122
+ country_code=country_code, country_name=country_name))
123
+ except Exception:
124
+ print("{index}. {country_code} - {country_name}".format(index=index,
125
+ country_code=country_code, country_name=country_code))
126
+
127
+
128
+ def print_calendar(
129
+ mode: str = "month",
130
+ timezone: Optional[str] = None,
131
+ country: Optional[str] = None,
132
+ v_shift: int = 0,
133
+ h_shift: int = 0,
134
+ date_system: str = "gregorian") -> None:
92
135
  """
93
136
  Print calendar.
94
137
 
95
138
  :param mode: calendar mode
96
- :type mode: str
97
139
  :param timezone: timezone
98
- :type timezone: str
140
+ :param country: country iso3166 code
99
141
  :param v_shift: vertical shift
100
- :type v_shift: int
101
142
  :param h_shift: horizontal shift
102
- :type h_shift: int
103
143
  :param date_system: date system
104
- :type date_system: str
105
- :return: None
106
144
  """
107
145
  datetime_lib = datetime
108
146
  calendar_obj = GregorianCalendar()
@@ -111,8 +149,12 @@ def print_calendar(mode="month", timezone=None, v_shift=0, h_shift=0, date_syste
111
149
  calendar_obj = JalaliCalendar()
112
150
  tz = None
113
151
  timezone_str = "Local"
152
+ if country is not None:
153
+ timezone = pytz.country_timezones(country)[0].upper()
114
154
  if timezone is not None:
115
155
  timezone_str = timezone
156
+ timezone_diff = get_timezone_difference(timezone=timezone)
157
+ timezone_str += " ({timezone_diff})".format(timezone_diff=timezone_diff)
116
158
  tz = pytz.timezone(timezone)
117
159
  v_shift = max(0, v_shift)
118
160
  h_shift = max(0, h_shift)
@@ -130,40 +172,31 @@ def print_calendar(mode="month", timezone=None, v_shift=0, h_shift=0, date_syste
130
172
 
131
173
 
132
174
  def run_clock(
133
- timezone=None,
134
- v_shift=0,
135
- h_shift=0,
136
- face=1,
137
- no_blink=False,
138
- vertical=False,
139
- hide_date=False,
140
- hide_timezone=False,
141
- am_pm=False,
142
- date_system="gregorian"):
175
+ timezone: Optional[str] = None,
176
+ country: Optional[str] = None,
177
+ v_shift: int = 0,
178
+ h_shift: int = 0,
179
+ face: int = 1,
180
+ no_blink: bool = False,
181
+ vertical: bool = False,
182
+ hide_date: bool = False,
183
+ hide_timezone: bool = False,
184
+ am_pm: bool = False,
185
+ date_system: str = "gregorian") -> None:
143
186
  """
144
187
  Run clock.
145
188
 
146
189
  :param timezone: timezone
147
- :type timezone: str
190
+ :param country: country iso3166 code
148
191
  :param v_shift: vertical shift
149
- :type v_shift: int
150
192
  :param h_shift: horizontal shift
151
- :type h_shift: int
152
193
  :param face: face index
153
- :type face: int
154
194
  :param no_blink: no-blink flag
155
- :type no_blink: bool
156
195
  :param vertical: vertical mode flag
157
- :type vertical: bool
158
196
  :param hide_date: hide date flag
159
- :type hide_date: bool
160
197
  :param hide_timezone: hide timezone flag
161
- :type hide_timezone: bool
162
198
  :param am_pm: AM/PM mode flag
163
- :type am_pm: bool
164
199
  :param date_system: date system
165
- :type date_system: str
166
- :return: None
167
200
  """
168
201
  datetime_lib = datetime
169
202
  if date_system == "jalali":
@@ -174,8 +207,12 @@ def run_clock(
174
207
  time_formats = VERTICAL_TIME_12H_FORMATS if am_pm else VERTICAL_TIME_24H_FORMATS
175
208
  tz = None
176
209
  timezone_str = "Local"
210
+ if country is not None:
211
+ timezone = pytz.country_timezones(country)[0].upper()
177
212
  if timezone is not None:
178
213
  timezone_str = timezone
214
+ timezone_diff = get_timezone_difference(timezone=timezone)
215
+ timezone_str += " ({timezone_diff})".format(timezone_diff=timezone_diff)
179
216
  tz = pytz.timezone(timezone)
180
217
  v_shift = max(0, v_shift)
181
218
  h_shift = max(0, h_shift)
@@ -199,15 +236,12 @@ def run_clock(
199
236
  format_index = int(not format_index)
200
237
 
201
238
 
202
- def main():
203
- """
204
- CLI main function.
205
-
206
- :return: None
207
- """
239
+ def main() -> None:
240
+ """CLI main function."""
208
241
  parser = argparse.ArgumentParser()
209
242
  parser.epilog = ADDITIONAL_INFO
210
- parser.add_argument('--timezone', help='timezone', type=str, choices=TIMEZONES_LIST)
243
+ parser.add_argument('--timezone', help='timezone', type=str.upper, choices=TIMEZONES_LIST)
244
+ parser.add_argument('--country', help='country (iso3166 code)', type=str.upper, choices=COUNTRIES_LIST)
211
245
  parser.add_argument('--v-shift', help='vertical shift', type=int, default=0)
212
246
  parser.add_argument('--h-shift', help='horizontal shift', type=int, default=0)
213
247
  parser.add_argument('--version', help='version', nargs="?", const=1)
@@ -215,13 +249,19 @@ def main():
215
249
  parser.add_argument('--face', help='face', type=int, choices=FACES_LIST, default=1)
216
250
  parser.add_argument('--faces-list', help='faces list', nargs="?", const=1)
217
251
  parser.add_argument('--timezones-list', help='timezones list', nargs="?", const=1)
252
+ parser.add_argument('--countries-list', help='countries list', nargs="?", const=1)
218
253
  parser.add_argument('--no-blink', help='disable blinking mode', nargs="?", const=1)
219
254
  parser.add_argument('--vertical', help='vertical mode', nargs="?", const=1)
220
255
  parser.add_argument('--hide-date', help='hide date', nargs="?", const=1)
221
256
  parser.add_argument('--hide-timezone', help='hide timezone', nargs="?", const=1)
222
257
  parser.add_argument('--am-pm', help='AM/PM mode', nargs="?", const=1)
223
- parser.add_argument('--calendar', help='calendar mode', type=str, choices=CALENDAR_LIST)
224
- parser.add_argument('--date-system', help='date system', type=str, choices=DATE_SYSTEMS_LIST, default="gregorian")
258
+ parser.add_argument('--calendar', help='calendar mode', type=str.lower, choices=CALENDARS_LIST)
259
+ parser.add_argument(
260
+ '--date-system',
261
+ help='date system',
262
+ type=str.lower,
263
+ choices=DATE_SYSTEMS_LIST,
264
+ default="gregorian")
225
265
  args = parser.parse_args()
226
266
  if args.version:
227
267
  print(CLOX_VERSION)
@@ -230,11 +270,14 @@ def main():
230
270
  elif args.faces_list:
231
271
  show_faces_list(vertical=args.vertical)
232
272
  elif args.timezones_list:
233
- show_timezones_list()
273
+ show_timezones_list(args.country)
274
+ elif args.countries_list:
275
+ show_countries_list()
234
276
  elif args.calendar:
235
277
  print_calendar(
236
278
  mode=args.calendar,
237
279
  timezone=args.timezone,
280
+ country=args.country,
238
281
  h_shift=args.h_shift,
239
282
  v_shift=args.v_shift,
240
283
  date_system=args.date_system)
@@ -242,6 +285,7 @@ def main():
242
285
  try:
243
286
  run_clock(
244
287
  timezone=args.timezone,
288
+ country=args.country,
245
289
  h_shift=args.h_shift,
246
290
  v_shift=args.v_shift,
247
291
  face=args.face,
@@ -1,6 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  """clox jalali calendar."""
3
3
  # Reference: https://github.com/IKermani/jcalendar
4
+ from typing import List, Tuple, Generator
4
5
  import datetime
5
6
  from itertools import repeat
6
7
  import jdatetime
@@ -13,7 +14,7 @@ error = ValueError
13
14
  class IllegalMonthError(ValueError):
14
15
  """Illegal month error."""
15
16
 
16
- def __init__(self, month):
17
+ def __init__(self, month: int) -> None:
17
18
  """Initiate."""
18
19
  self.month = month
19
20
 
@@ -25,7 +26,7 @@ class IllegalMonthError(ValueError):
25
26
  class IllegalWeekdayError(ValueError):
26
27
  """Illegal weekday error."""
27
28
 
28
- def __init__(self, weekday):
29
+ def __init__(self, weekday: int) -> None:
29
30
  """Initiate."""
30
31
  self.weekday = weekday
31
32
 
@@ -58,12 +59,12 @@ month_abbr = [0] + jdatetime.date.j_months_short_en
58
59
  (DOSHANBE, SESHANBE, CHAHARSHANBE, PANJSHANBE, JOME, SHANBE, YEKSHANBE) = range(7)
59
60
 
60
61
 
61
- def isleap(year):
62
+ def isleap(year: int) -> bool:
62
63
  """Return True for leap years, False for non-leap years."""
63
64
  return jdatetime.date(year, 1, 1).isleap()
64
65
 
65
66
 
66
- def leapdays(y1, y2):
67
+ def leapdays(y1: int, y2: int) -> int:
67
68
  """Return number of leap years in range [y1, y2)."""
68
69
  leapdays = 0
69
70
 
@@ -74,14 +75,14 @@ def leapdays(y1, y2):
74
75
  return leapdays
75
76
 
76
77
 
77
- def weekday(year, month, day):
78
+ def weekday(year: int, month: int, day: int) -> int:
78
79
  """Return week-day (0-6 ~ Mon-Sun)."""
79
80
  if not datetime.MINYEAR <= year <= datetime.MAXYEAR:
80
81
  year = 2000 + year % 400
81
82
  return jdatetime.date(year, month, day).weekday()
82
83
 
83
84
 
84
- def monthrange(year, month):
85
+ def monthrange(year: int, month: int) -> Tuple[int, int]:
85
86
  """Return weekday (0-6 ~ Mon-Sun) and number of days (28-31) for year, month."""
86
87
  if not 1 <= month <= 12:
87
88
  raise IllegalMonthError(month)
@@ -90,12 +91,12 @@ def monthrange(year, month):
90
91
  return day1, ndays
91
92
 
92
93
 
93
- def _monthlen(year, month):
94
+ def _monthlen(year: int, month: int) -> int:
94
95
  """Return length of month."""
95
96
  return mdays[month] + (month == Esfand and isleap(year))
96
97
 
97
98
 
98
- def _prevmonth(year, month):
99
+ def _prevmonth(year: int, month: int) -> Tuple[int, int]:
99
100
  """Return previous month."""
100
101
  if month == 1:
101
102
  return year - 1, 12
@@ -103,7 +104,7 @@ def _prevmonth(year, month):
103
104
  return year, month - 1
104
105
 
105
106
 
106
- def _nextmonth(year, month):
107
+ def _nextmonth(year: int, month: int) -> Tuple[int, int]:
107
108
  """Return next month."""
108
109
  if month == 12:
109
110
  return year + 1, 1
@@ -111,34 +112,34 @@ def _nextmonth(year, month):
111
112
  return year, month + 1
112
113
 
113
114
 
114
- class Calendar(object):
115
+ class Calendar:
115
116
  """Base calendar class. This class doesn't do any formatting. It simply provides data to subclasses."""
116
117
 
117
- def __init__(self, firstweekday=0):
118
+ def __init__(self, firstweekday: int = 0) -> None:
118
119
  """Initiate."""
119
120
  self.firstweekday = firstweekday # 0 = Doshanbe, 6 = Yekshanbe
120
121
 
121
- def getfirstweekday(self):
122
+ def getfirstweekday(self) -> int:
122
123
  """Get first weekday."""
123
124
  return self._firstweekday % 7
124
125
 
125
- def setfirstweekday(self, firstweekday):
126
+ def setfirstweekday(self, firstweekday: int) -> None:
126
127
  """Set first weekday."""
127
128
  self._firstweekday = firstweekday
128
129
 
129
130
  firstweekday = property(getfirstweekday, setfirstweekday)
130
131
 
131
- def iterweekdays(self):
132
+ def iterweekdays(self) -> Generator[int, None, None]:
132
133
  """Return an iterator for one week of weekday numbers starting with the configured first one."""
133
134
  for i in range(self.firstweekday, self.firstweekday + 7):
134
135
  yield i % 7
135
136
 
136
- def itermonthdates(self, year, month):
137
+ def itermonthdates(self, year: int, month: int) -> Generator[jdatetime.date, None, None]:
137
138
  """Return an iterator for one month."""
138
139
  for y, m, d in self.itermonthdays3(year, month):
139
140
  yield jdatetime.date(y, m, d)
140
141
 
141
- def itermonthdays(self, year, month):
142
+ def itermonthdays(self, year: int, month: int) -> Generator[int, None, None]:
142
143
  """Like itermonthdates(), but will yield day numbers. For days outside the specified month the day number is 0."""
143
144
  day1, ndays = monthrange(year, month)
144
145
  days_before = (day1 - self.firstweekday) % 7
@@ -147,12 +148,12 @@ class Calendar(object):
147
148
  days_after = (self.firstweekday - day1 - ndays) % 7
148
149
  yield from repeat(0, days_after)
149
150
 
150
- def itermonthdays2(self, year, month):
151
+ def itermonthdays2(self, year: int, month: int) -> Generator[Tuple[int, int], None, None]:
151
152
  """Like itermonthdates(), but will yield (day number, weekday number) tuples. For days outside the specified month the day number is 0."""
152
153
  for i, d in enumerate(self.itermonthdays(year, month), self.firstweekday):
153
154
  yield d, i % 7
154
155
 
155
- def itermonthdays3(self, year, month):
156
+ def itermonthdays3(self, year: int, month: int) -> Generator[Tuple[int, int, int], None, None]:
156
157
  """Like itermonthdates(), but will yield (year, month, day) tuples. Can be used for dates outside of datetime.date range."""
157
158
  day1, ndays = monthrange(year, month)
158
159
  days_before = (day1 - self.firstweekday) % 7
@@ -167,27 +168,27 @@ class Calendar(object):
167
168
  for d in range(1, days_after + 1):
168
169
  yield y, m, d
169
170
 
170
- def itermonthdays4(self, year, month):
171
+ def itermonthdays4(self, year: int, month: int) -> Generator[Tuple[int, int, int, int], None, None]:
171
172
  """Like itermonthdates(), but will yield (year, month, day, day_of_week) tuples. Can be used for dates outside of datetime.date range."""
172
173
  for i, (y, m, d) in enumerate(self.itermonthdays3(year, month)):
173
174
  yield y, m, d, (self.firstweekday + i) % 7
174
175
 
175
- def monthdatescalendar(self, year, month):
176
+ def monthdatescalendar(self, year: int, month: int) -> List[List[jdatetime.date]]:
176
177
  """Return a matrix (list of lists) representing a month's calendar.Each row represents a week; week entries are datetime.date values."""
177
178
  dates = list(self.itermonthdates(year, month))
178
179
  return [dates[i:i + 7] for i in range(0, len(dates), 7)]
179
180
 
180
- def monthdays2calendar(self, year, month):
181
+ def monthdays2calendar(self, year: int, month: int) -> List[List[Tuple[int, int]]]:
181
182
  """Return a matrix representing a month's calendar."""
182
183
  days = list(self.itermonthdays2(year, month))
183
184
  return [days[i:i + 7] for i in range(0, len(days), 7)]
184
185
 
185
- def monthdayscalendar(self, year, month):
186
+ def monthdayscalendar(self, year: int, month: int) -> List[List[int]]:
186
187
  """Return a matrix representing a month's calendar."""
187
188
  days = list(self.itermonthdays(year, month))
188
189
  return [days[i:i + 7] for i in range(0, len(days), 7)]
189
190
 
190
- def yeardatescalendar(self, year, width=3):
191
+ def yeardatescalendar(self, year: int, width: int = 3) -> List[List[List[List[jdatetime.date]]]]:
191
192
  """Return the data for the specified year ready for formatting."""
192
193
  months = [
193
194
  self.monthdatescalendar(year, i)
@@ -195,7 +196,7 @@ class Calendar(object):
195
196
  ]
196
197
  return [months[i:i + width] for i in range(0, len(months), width)]
197
198
 
198
- def yeardays2calendar(self, year, width=3):
199
+ def yeardays2calendar(self, year: int, width: int = 3) -> List[List[List[List[Tuple[int, int]]]]]:
199
200
  """Return the data for the specified year ready for formatting."""
200
201
  months = [
201
202
  self.monthdays2calendar(year, i)
@@ -203,7 +204,7 @@ class Calendar(object):
203
204
  ]
204
205
  return [months[i:i + width] for i in range(0, len(months), width)]
205
206
 
206
- def yeardayscalendar(self, year, width=3):
207
+ def yeardayscalendar(self, year: int, width: int = 3) -> List[List[List[int]]]:
207
208
  """Return the data for the specified year ready for formatting."""
208
209
  months = [
209
210
  self.monthdayscalendar(year, i)
@@ -215,11 +216,11 @@ class Calendar(object):
215
216
  class TextCalendar(Calendar):
216
217
  """Subclass of Calendar that outputs a calendar as a simple plain text similar to the UNIX program cal."""
217
218
 
218
- def prweek(self, theweek, width):
219
+ def prweek(self, theweek: List[Tuple[int, int]], width: int) -> None:
219
220
  """Print a single week (no newline)."""
220
221
  print(self.formatweek(theweek, width), end='')
221
222
 
222
- def formatday(self, day, weekday, width):
223
+ def formatday(self, day: int, width: int) -> str:
223
224
  """Return a formatted day."""
224
225
  if day == 0:
225
226
  s = ''
@@ -227,11 +228,11 @@ class TextCalendar(Calendar):
227
228
  s = '%2i' % day # right-align single-digit days
228
229
  return s.center(width)
229
230
 
230
- def formatweek(self, theweek, width):
231
+ def formatweek(self, theweek: List[Tuple[int, int]], width: int) -> str:
231
232
  """Return a single week in a string (no newline)."""
232
- return ' '.join(self.formatday(d, wd, width) for (d, wd) in theweek)
233
+ return ' '.join(self.formatday(d, width) for d, _ in theweek)
233
234
 
234
- def formatweekday(self, day, width):
235
+ def formatweekday(self, day: int, width: int) -> str:
235
236
  """Return a formatted week day name."""
236
237
  if width >= 9:
237
238
  names = day_name
@@ -239,22 +240,22 @@ class TextCalendar(Calendar):
239
240
  names = day_abbr
240
241
  return names[day][:width].center(width)
241
242
 
242
- def formatweekheader(self, width):
243
+ def formatweekheader(self, width: int) -> str:
243
244
  """Return a header for a week."""
244
245
  return ' '.join(self.formatweekday(i, width) for i in self.iterweekdays())
245
246
 
246
- def formatmonthname(self, theyear, themonth, width, withyear=True):
247
+ def formatmonthname(self, theyear: int, themonth: int, width: int, withyear: bool = True) -> str:
247
248
  """Return a formatted month name."""
248
249
  s = month_name[themonth]
249
250
  if withyear:
250
251
  s = "%s %r" % (s, theyear)
251
252
  return s.center(width)
252
253
 
253
- def prmonth(self, theyear, themonth, w=0, l=0):
254
+ def prmonth(self, theyear: int, themonth: int, w: int = 0, l: int = 0) -> None:
254
255
  """Print a month's calendar."""
255
256
  print(self.formatmonth(theyear, themonth, w, l), end='')
256
257
 
257
- def formatmonth(self, theyear, themonth, w=0, l=0):
258
+ def formatmonth(self, theyear: int, themonth: int, w: int = 0, l: int = 0) -> str:
258
259
  """Return a month's calendar string (multi-line)."""
259
260
  w = max(2, w)
260
261
  l = max(1, l)
@@ -268,7 +269,7 @@ class TextCalendar(Calendar):
268
269
  s += '\n' * l
269
270
  return s
270
271
 
271
- def formatyear(self, theyear, w=2, l=1, c=6, m=3):
272
+ def formatyear(self, theyear: int, w: int = 2, l: int = 1, c: int = 6, m: int = 3) -> str:
272
273
  """Return a year's calendar as a multi-line string."""
273
274
  w = max(2, w)
274
275
  l = max(1, l)
@@ -303,7 +304,7 @@ class TextCalendar(Calendar):
303
304
  a('\n' * l)
304
305
  return ''.join(v)
305
306
 
306
- def pryear(self, theyear, w=0, l=0, c=6, m=3):
307
+ def pryear(self, theyear: int, w: int = 0, l: int = 0, c: int = 6, m: int = 3) -> None:
307
308
  """Print a year's calendar."""
308
309
  print(self.formatyear(theyear, w, l, c, m), end='')
309
310
 
@@ -313,7 +314,7 @@ c = TextCalendar()
313
314
  firstweekday = c.getfirstweekday
314
315
 
315
316
 
316
- def setfirstweekday(firstweekday):
317
+ def setfirstweekday(firstweekday: int) -> None:
317
318
  """Set first weekday."""
318
319
  if not DOSHANBE <= firstweekday <= YEKSHANBE:
319
320
  raise IllegalWeekdayError(firstweekday)
@@ -334,12 +335,12 @@ _colwidth = 7 * 3 - 1 # Amount printed by prweek()
334
335
  _spacing = 6 # Number of spaces between columns
335
336
 
336
337
 
337
- def format(cols, colwidth=_colwidth, spacing=_spacing):
338
+ def format(cols: List[str], colwidth: int = _colwidth, spacing: int = _spacing) -> None:
338
339
  """Print multi-column formatting for year calendars."""
339
340
  print(formatstring(cols, colwidth, spacing))
340
341
 
341
342
 
342
- def formatstring(cols, colwidth=_colwidth, spacing=_spacing):
343
+ def formatstring(cols: List[str], colwidth: int = _colwidth, spacing: int = _spacing) -> str:
343
344
  """Return a string formatted from n strings, centered within n columns."""
344
345
  spacing *= ' '
345
346
  return spacing.join(c.center(colwidth) for c in cols)
@@ -349,7 +350,7 @@ EPOCH = 1970
349
350
  _EPOCH_ORD = jdatetime.date(EPOCH, 1, 1).toordinal()
350
351
 
351
352
 
352
- def timegm(tuple):
353
+ def timegm(tuple: Tuple) -> int:
353
354
  """Unrelated but handy function to calculate Unix timestamp from GMT."""
354
355
  year, month, day, hour, minute, second = tuple[:6]
355
356
  days = jdatetime.date(year, month, 1).toordinal() - _EPOCH_ORD + day - 1
@@ -2,7 +2,7 @@
2
2
  """clox params."""
3
3
  import pytz
4
4
 
5
- CLOX_VERSION = "0.7"
5
+ CLOX_VERSION = "0.9"
6
6
 
7
7
  CLOX_OVERVIEW = '''
8
8
  Clox is a terminal-based clock application designed for terminal enthusiasts who appreciate simplicity,
@@ -23,8 +23,10 @@ VERTICAL_TIME_24H_FORMATS = ['%H\n%M', '%H\n%M.']
23
23
  HORIZONTAL_TIME_12H_FORMATS = ['%I:%M %p', '%I:%M %p.']
24
24
  VERTICAL_TIME_12H_FORMATS = ['%I\n%M\n%p', '%I\n%M\n%p.']
25
25
  DATE_FORMAT = "%A, %B %d, %Y"
26
+ TIMEZONE_DIFFERENCE_FORMAT = "{hours:02}h{minutes:02}m {direction}"
26
27
 
27
- TIMEZONES_LIST = pytz.all_timezones
28
+ TIMEZONES_LIST = list(map(lambda x: x.upper(), pytz.all_timezones))
29
+ COUNTRIES_LIST = list(map(lambda x: x.upper(), pytz.country_timezones.keys()))
28
30
 
29
31
 
30
32
  FACES_MAP = {
@@ -57,6 +59,6 @@ FACES_MAP = {
57
59
 
58
60
  FACES_LIST = [-1] + sorted(FACES_MAP)
59
61
 
60
- CALENDAR_LIST = ["month", "year"]
62
+ CALENDARS_LIST = ["month", "year"]
61
63
 
62
64
  DATE_SYSTEMS_LIST = ["gregorian", "jalali"]
@@ -1,9 +1,9 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: clox
3
- Version: 0.7
3
+ Version: 0.9
4
4
  Summary: A Geeky Clock for Terminal Enthusiasts
5
5
  Home-page: https://github.com/sepandhaghighi/clox
6
- Download-URL: https://github.com/sepandhaghighi/clox/tarball/v0.7
6
+ Download-URL: https://github.com/sepandhaghighi/clox/tarball/v0.9
7
7
  Author: Sepand Haghighi
8
8
  Author-email: me@sepand.tech
9
9
  License: MIT
@@ -13,7 +13,6 @@ Classifier: Development Status :: 4 - Beta
13
13
  Classifier: Natural Language :: English
14
14
  Classifier: License :: OSI Approved :: MIT License
15
15
  Classifier: Operating System :: OS Independent
16
- Classifier: Programming Language :: Python :: 3.6
17
16
  Classifier: Programming Language :: Python :: 3.7
18
17
  Classifier: Programming Language :: Python :: 3.8
19
18
  Classifier: Programming Language :: Python :: 3.9
@@ -27,7 +26,7 @@ Classifier: Intended Audience :: End Users/Desktop
27
26
  Classifier: Intended Audience :: Other Audience
28
27
  Classifier: Topic :: Games/Entertainment
29
28
  Classifier: Topic :: Utilities
30
- Requires-Python: >=3.6
29
+ Requires-Python: >=3.7
31
30
  Description-Content-Type: text/markdown
32
31
  License-File: LICENSE
33
32
  License-File: AUTHORS.md
@@ -43,6 +42,7 @@ Dynamic: download-url
43
42
  Dynamic: home-page
44
43
  Dynamic: keywords
45
44
  Dynamic: license
45
+ Dynamic: license-file
46
46
  Dynamic: project-url
47
47
  Dynamic: requires-dist
48
48
  Dynamic: requires-python
@@ -104,13 +104,13 @@ Clox is a terminal-based clock application designed for terminal enthusiasts who
104
104
  ## Installation
105
105
 
106
106
  ### Source Code
107
- - Download [Version 0.7](https://github.com/sepandhaghighi/clox/archive/v0.7.zip) or [Latest Source](https://github.com/sepandhaghighi/clox/archive/dev.zip)
107
+ - Download [Version 0.9](https://github.com/sepandhaghighi/clox/archive/v0.9.zip) or [Latest Source](https://github.com/sepandhaghighi/clox/archive/dev.zip)
108
108
  - `pip install .`
109
109
 
110
110
  ### PyPI
111
111
 
112
112
  - Check [Python Packaging User Guide](https://packaging.python.org/installing/)
113
- - `pip install clox==0.7`
113
+ - `pip install clox==0.9`
114
114
 
115
115
 
116
116
  ## Usage
@@ -143,16 +143,30 @@ clox
143
143
  clox --face=3
144
144
  ```
145
145
  * Use `--face=-1` for random mode
146
- * [Faces List](https://github.com/sepandhaghighi/clox/blob/main/FACES.md)
147
- * `clox --faces-list`
146
+ * [Faces List](https://github.com/sepandhaghighi/clox/blob/main/FACES.md): `clox --faces-list`
147
+
148
148
 
149
149
  ### Timezone
150
150
 
151
151
  ```console
152
152
  clox --timezone="Etc/GMT+7"
153
153
  ```
154
- * [Timezones List](https://github.com/sepandhaghighi/clox/blob/main/TIMEZONES.md)
155
- * `clox --timezones-list`
154
+ * [Timezones List](https://github.com/sepandhaghighi/clox/blob/main/TIMEZONES.md): `clox --timezones-list`
155
+
156
+
157
+ ### Country
158
+
159
+ The `--country` argument allows you to specify a country using its **ISO 3166** code format
160
+
161
+ ℹ️ When the `--country` argument is provided, the `--timezone` argument will be ignored
162
+
163
+ ℹ️ If the specified country has multiple timezones, the first timezone will be selected automatically
164
+
165
+ ```console
166
+ clox --country="DE"
167
+ ```
168
+ * [Countries List](https://github.com/sepandhaghighi/clox/blob/main/COUNTRIES.md): `clox --countries-list`
169
+
156
170
 
157
171
  ### Vertical/Horizontal Shift
158
172
 
@@ -278,6 +292,22 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
278
292
  and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
279
293
 
280
294
  ## [Unreleased]
295
+ ## [0.9] - 2025-04-14
296
+ ### Added
297
+ - Timezone difference
298
+ ### Changed
299
+ - Python typing features added to all modules
300
+ - Test system modified
301
+ - `Python 3.6` support dropped
302
+ ## [0.8] - 2025-03-16
303
+ ### Added
304
+ - `--country` argument
305
+ - `--countries-list` argument
306
+ - `COUNTRIES.md`
307
+ ### Changed
308
+ - Input case sensitivity bug fixed
309
+ - Test system modified
310
+ - `README.md` updated
281
311
  ## [0.7] - 2025-03-06
282
312
  ### Added
283
313
  - Jalali calendar
@@ -322,7 +352,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
322
352
  - `TIMEZONES.md`
323
353
  - `FACES.md`
324
354
 
325
- [Unreleased]: https://github.com/sepandhaghighi/clox/compare/v0.7...dev
355
+ [Unreleased]: https://github.com/sepandhaghighi/clox/compare/v0.9...dev
356
+ [0.9]: https://github.com/sepandhaghighi/clox/compare/v0.8...v0.9
357
+ [0.8]: https://github.com/sepandhaghighi/clox/compare/v0.7...v0.8
326
358
  [0.7]: https://github.com/sepandhaghighi/clox/compare/v0.6...v0.7
327
359
  [0.6]: https://github.com/sepandhaghighi/clox/compare/v0.5...v0.6
328
360
  [0.5]: https://github.com/sepandhaghighi/clox/compare/v0.4...v0.5
@@ -1,5 +1,6 @@
1
1
  AUTHORS.md
2
2
  CHANGELOG.md
3
+ COUNTRIES.md
3
4
  FACES.md
4
5
  LICENSE
5
6
  MANIFEST.in
@@ -1,5 +1,5 @@
1
1
  jdatetime==5.2.0
2
- pytz==2025.1
2
+ pytz==2025.2
3
3
  art==6.4
4
4
  setuptools>=40.8.0
5
5
  vulture>=1.0
@@ -1,18 +1,19 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  """Setup module."""
3
+ from typing import List
3
4
  try:
4
5
  from setuptools import setup
5
6
  except ImportError:
6
7
  from distutils.core import setup
7
8
 
8
9
 
9
- def get_requires():
10
+ def get_requires() -> List[str]:
10
11
  """Read requirements.txt."""
11
12
  requirements = open("requirements.txt", "r").read()
12
13
  return list(filter(lambda x: x != "", requirements.split()))
13
14
 
14
15
 
15
- def read_description():
16
+ def read_description() -> str:
16
17
  """Read README.md and CHANGELOG.md."""
17
18
  try:
18
19
  with open("README.md") as r:
@@ -29,7 +30,7 @@ def read_description():
29
30
  setup(
30
31
  name='clox',
31
32
  packages=['clox'],
32
- version='0.7',
33
+ version='0.9',
33
34
  description='A Geeky Clock for Terminal Enthusiasts',
34
35
  long_description=read_description(),
35
36
  long_description_content_type='text/markdown',
@@ -37,19 +38,18 @@ setup(
37
38
  author='Sepand Haghighi',
38
39
  author_email='me@sepand.tech',
39
40
  url='https://github.com/sepandhaghighi/clox',
40
- download_url='https://github.com/sepandhaghighi/clox/tarball/v0.7',
41
+ download_url='https://github.com/sepandhaghighi/clox/tarball/v0.9',
41
42
  keywords="clock time timer timezone terminal cli geek clox",
42
43
  project_urls={
43
44
  'Source': 'https://github.com/sepandhaghighi/clox'
44
45
  },
45
46
  install_requires=get_requires(),
46
- python_requires='>=3.6',
47
+ python_requires='>=3.7',
47
48
  classifiers=[
48
49
  'Development Status :: 4 - Beta',
49
50
  'Natural Language :: English',
50
51
  'License :: OSI Approved :: MIT License',
51
52
  'Operating System :: OS Independent',
52
- 'Programming Language :: Python :: 3.6',
53
53
  'Programming Language :: Python :: 3.7',
54
54
  'Programming Language :: Python :: 3.8',
55
55
  'Programming Language :: Python :: 3.9',
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes