clox 0.8__py3-none-any.whl → 0.9__py3-none-any.whl

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.

clox/functions.py CHANGED
@@ -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,6 +14,7 @@ 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
17
+ from .params import TIMEZONE_DIFFERENCE_FORMAT
16
18
  from .params import CLOX_VERSION, DATE_FORMAT
17
19
  from .params import TIMEZONES_LIST, COUNTRIES_LIST
18
20
  from .params import ADDITIONAL_INFO, EXIT_MESSAGE
@@ -21,50 +23,63 @@ from .params import HORIZONTAL_FACES_LIST_EXAMPLE, VERTICAL_FACES_LIST_EXAMPLE
21
23
  from .params import CLOX_OVERVIEW, CLOX_REPO
22
24
 
23
25
 
24
- def clox_info():
25
- """
26
- Print clox details.
27
-
28
- :return: None
29
- """
26
+ def clox_info() -> None:
27
+ """Print clox details."""
30
28
  tprint("Clox")
31
29
  tprint("V:" + CLOX_VERSION)
32
30
  print(CLOX_OVERVIEW)
33
31
  print(CLOX_REPO)
34
32
 
35
33
 
36
- def clear_screen():
37
- """
38
- Clear screen function.
39
-
40
- :return: None
41
- """
34
+ def clear_screen() -> None:
35
+ """Clear screen function."""
42
36
  if sys.platform == "win32":
43
37
  os.system('cls')
44
38
  else:
45
39
  os.system('clear')
46
40
 
47
41
 
48
- def get_face(index):
42
+ def get_face(index: int) -> str:
49
43
  """
50
44
  Return face name.
51
45
 
52
46
  :param index: face index
53
- :type index: int
54
- :return: face name as str
55
47
  """
56
48
  if index == -1:
57
49
  index = random.choice(sorted(FACES_MAP))
58
50
  return FACES_MAP[index]
59
51
 
60
52
 
61
- 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:
62
79
  """
63
80
  Show faces list.
64
81
 
65
82
  :param vertical: vertical mode flag
66
- :type vertical: bool
67
- :return: None
68
83
  """
69
84
  mode = "Horizontal"
70
85
  example = HORIZONTAL_FACES_LIST_EXAMPLE
@@ -78,13 +93,11 @@ def show_faces_list(vertical=False):
78
93
  print('=' * 80)
79
94
 
80
95
 
81
- def show_timezones_list(country=None):
96
+ def show_timezones_list(country: Optional[str] = None) -> None:
82
97
  """
83
98
  Show timezones list.
84
99
 
85
100
  :param country: country iso3166 code
86
- :type country: str
87
- :return: None
88
101
  """
89
102
  timezones_list = TIMEZONES_LIST
90
103
  country_name = "All"
@@ -99,12 +112,8 @@ def show_timezones_list(country=None):
99
112
  print("{index}. {timezone}".format(index=index, timezone=timezone))
100
113
 
101
114
 
102
- def show_countries_list():
103
- """
104
- Show countries list.
105
-
106
- :return: None
107
- """
115
+ def show_countries_list() -> None:
116
+ """Show countries list."""
108
117
  print("Countries list:\n")
109
118
  for index, country_code in enumerate(sorted(COUNTRIES_LIST), 1):
110
119
  country_name = pytz.country_names[country_code]
@@ -116,23 +125,22 @@ def show_countries_list():
116
125
  country_code=country_code, country_name=country_code))
117
126
 
118
127
 
119
- def print_calendar(mode="month", timezone=None, country=None, v_shift=0, h_shift=0, date_system="gregorian"):
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:
120
135
  """
121
136
  Print calendar.
122
137
 
123
138
  :param mode: calendar mode
124
- :type mode: str
125
139
  :param timezone: timezone
126
- :type timezone: str
127
140
  :param country: country iso3166 code
128
- :type country: str
129
141
  :param v_shift: vertical shift
130
- :type v_shift: int
131
142
  :param h_shift: horizontal shift
132
- :type h_shift: int
133
143
  :param date_system: date system
134
- :type date_system: str
135
- :return: None
136
144
  """
137
145
  datetime_lib = datetime
138
146
  calendar_obj = GregorianCalendar()
@@ -145,6 +153,8 @@ def print_calendar(mode="month", timezone=None, country=None, v_shift=0, h_shift
145
153
  timezone = pytz.country_timezones(country)[0].upper()
146
154
  if timezone is not None:
147
155
  timezone_str = timezone
156
+ timezone_diff = get_timezone_difference(timezone=timezone)
157
+ timezone_str += " ({timezone_diff})".format(timezone_diff=timezone_diff)
148
158
  tz = pytz.timezone(timezone)
149
159
  v_shift = max(0, v_shift)
150
160
  h_shift = max(0, h_shift)
@@ -162,43 +172,31 @@ def print_calendar(mode="month", timezone=None, country=None, v_shift=0, h_shift
162
172
 
163
173
 
164
174
  def run_clock(
165
- timezone=None,
166
- country=None,
167
- v_shift=0,
168
- h_shift=0,
169
- face=1,
170
- no_blink=False,
171
- vertical=False,
172
- hide_date=False,
173
- hide_timezone=False,
174
- am_pm=False,
175
- 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:
176
186
  """
177
187
  Run clock.
178
188
 
179
189
  :param timezone: timezone
180
- :type timezone: str
181
190
  :param country: country iso3166 code
182
- :type country: str
183
191
  :param v_shift: vertical shift
184
- :type v_shift: int
185
192
  :param h_shift: horizontal shift
186
- :type h_shift: int
187
193
  :param face: face index
188
- :type face: int
189
194
  :param no_blink: no-blink flag
190
- :type no_blink: bool
191
195
  :param vertical: vertical mode flag
192
- :type vertical: bool
193
196
  :param hide_date: hide date flag
194
- :type hide_date: bool
195
197
  :param hide_timezone: hide timezone flag
196
- :type hide_timezone: bool
197
198
  :param am_pm: AM/PM mode flag
198
- :type am_pm: bool
199
199
  :param date_system: date system
200
- :type date_system: str
201
- :return: None
202
200
  """
203
201
  datetime_lib = datetime
204
202
  if date_system == "jalali":
@@ -213,6 +211,8 @@ def run_clock(
213
211
  timezone = pytz.country_timezones(country)[0].upper()
214
212
  if timezone is not None:
215
213
  timezone_str = timezone
214
+ timezone_diff = get_timezone_difference(timezone=timezone)
215
+ timezone_str += " ({timezone_diff})".format(timezone_diff=timezone_diff)
216
216
  tz = pytz.timezone(timezone)
217
217
  v_shift = max(0, v_shift)
218
218
  h_shift = max(0, h_shift)
@@ -236,12 +236,8 @@ def run_clock(
236
236
  format_index = int(not format_index)
237
237
 
238
238
 
239
- def main():
240
- """
241
- CLI main function.
242
-
243
- :return: None
244
- """
239
+ def main() -> None:
240
+ """CLI main function."""
245
241
  parser = argparse.ArgumentParser()
246
242
  parser.epilog = ADDITIONAL_INFO
247
243
  parser.add_argument('--timezone', help='timezone', type=str.upper, choices=TIMEZONES_LIST)
clox/jcalendar.py CHANGED
@@ -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
clox/params.py CHANGED
@@ -2,7 +2,7 @@
2
2
  """clox params."""
3
3
  import pytz
4
4
 
5
- CLOX_VERSION = "0.8"
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,6 +23,7 @@ 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
28
  TIMEZONES_LIST = list(map(lambda x: x.upper(), pytz.all_timezones))
28
29
  COUNTRIES_LIST = list(map(lambda x: x.upper(), pytz.country_timezones.keys()))
@@ -1,9 +1,9 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: clox
3
- Version: 0.8
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.8
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.8](https://github.com/sepandhaghighi/clox/archive/v0.8.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.8`
113
+ - `pip install clox==0.9`
114
114
 
115
115
 
116
116
  ## Usage
@@ -292,6 +292,13 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
292
292
  and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
293
293
 
294
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
295
302
  ## [0.8] - 2025-03-16
296
303
  ### Added
297
304
  - `--country` argument
@@ -345,7 +352,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
345
352
  - `TIMEZONES.md`
346
353
  - `FACES.md`
347
354
 
348
- [Unreleased]: https://github.com/sepandhaghighi/clox/compare/v0.8...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
349
357
  [0.8]: https://github.com/sepandhaghighi/clox/compare/v0.7...v0.8
350
358
  [0.7]: https://github.com/sepandhaghighi/clox/compare/v0.6...v0.7
351
359
  [0.6]: https://github.com/sepandhaghighi/clox/compare/v0.5...v0.6
@@ -0,0 +1,12 @@
1
+ clox/__init__.py,sha256=gErclFSjUDschQpngWqOBGkBKt1jwd-Ww8B9iJmlU5s,108
2
+ clox/__main__.py,sha256=9oJYc1WXu4ZMrjKny_2-4Cgu46-VWHuE9xOqD1iJY0E,109
3
+ clox/functions.py,sha256=E5-nMw4OlASGsuSUO3TvoD3J2E1y7QFsz5cVAwYOF5M,10838
4
+ clox/jcalendar.py,sha256=RvtTikECGI4LjDSi5qbJF9grz7to2__fgR98xnnvme8,13462
5
+ clox/params.py,sha256=fUTq-i9Lr2oHj7mwXvuW9NaBjWmou0MTiEqcdNR0wg4,1722
6
+ clox-0.9.dist-info/licenses/AUTHORS.md,sha256=lmtnd18MnfgB57jdvfJbC0JHN3iARf2Ov4pY5kPGJC8,242
7
+ clox-0.9.dist-info/licenses/LICENSE,sha256=WoAsqqZ_lNVBGdyxjwh7YnVNXKfOB-qYVrRhrn-e-_4,1072
8
+ clox-0.9.dist-info/METADATA,sha256=pGZb1PCNl_wmayj6H6FzfdFjU1DoJNdBukRAG3Yx1RM,9713
9
+ clox-0.9.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
10
+ clox-0.9.dist-info/entry_points.txt,sha256=sP4Rmoe-DxYGjlF_Tld6nghbt_u-fK8h9ZUQFmO8TJs,45
11
+ clox-0.9.dist-info/top_level.txt,sha256=5DxGH-4VNfYkM8vbfngObh6-jpFEoSW4M90EvDGfhSw,5
12
+ clox-0.9.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (76.0.0)
2
+ Generator: setuptools (78.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
clox-0.8.dist-info/RECORD DELETED
@@ -1,12 +0,0 @@
1
- clox/__init__.py,sha256=gErclFSjUDschQpngWqOBGkBKt1jwd-Ww8B9iJmlU5s,108
2
- clox/__main__.py,sha256=9oJYc1WXu4ZMrjKny_2-4Cgu46-VWHuE9xOqD1iJY0E,109
3
- clox/functions.py,sha256=rHrWxzW0NxARlaKaUlO-TXEPyhEG1MQ0jctDxBe192I,10008
4
- clox/jcalendar.py,sha256=yAzuyXq6h8D5aJG_He_WuPR8Xy411W_l7pl8mtPJa5U,12296
5
- clox/params.py,sha256=8rlLAfUv3nHNVh5cSsH_1O1aNQoDAgmyKxiTkqV8f54,1654
6
- clox-0.8.dist-info/AUTHORS.md,sha256=lmtnd18MnfgB57jdvfJbC0JHN3iARf2Ov4pY5kPGJC8,242
7
- clox-0.8.dist-info/LICENSE,sha256=WoAsqqZ_lNVBGdyxjwh7YnVNXKfOB-qYVrRhrn-e-_4,1072
8
- clox-0.8.dist-info/METADATA,sha256=-c6IkxbwAxVIm0VY_MU9GICTe9v6xrtErvXEMHOr0iw,9509
9
- clox-0.8.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
10
- clox-0.8.dist-info/entry_points.txt,sha256=sP4Rmoe-DxYGjlF_Tld6nghbt_u-fK8h9ZUQFmO8TJs,45
11
- clox-0.8.dist-info/top_level.txt,sha256=5DxGH-4VNfYkM8vbfngObh6-jpFEoSW4M90EvDGfhSw,5
12
- clox-0.8.dist-info/RECORD,,
File without changes