libdev 0.84__tar.gz → 0.86__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.
- {libdev-0.84 → libdev-0.86}/PKG-INFO +1 -1
- {libdev-0.84 → libdev-0.86}/libdev/__init__.py +1 -1
- {libdev-0.84 → libdev-0.86}/libdev/crypt.py +3 -2
- {libdev-0.84 → libdev-0.86}/libdev/time.py +119 -0
- {libdev-0.84 → libdev-0.86}/libdev.egg-info/PKG-INFO +1 -1
- {libdev-0.84 → libdev-0.86}/tests/test_crypt.py +3 -3
- {libdev-0.84 → libdev-0.86}/tests/test_s3.py +0 -0
- {libdev-0.84 → libdev-0.86}/tests/test_time.py +41 -1
- {libdev-0.84 → libdev-0.86}/LICENSE +0 -0
- {libdev-0.84 → libdev-0.86}/README.md +0 -0
- {libdev-0.84 → libdev-0.86}/libdev/cfg.py +0 -0
- {libdev-0.84 → libdev-0.86}/libdev/check.py +0 -0
- {libdev-0.84 → libdev-0.86}/libdev/codes.py +0 -0
- {libdev-0.84 → libdev-0.86}/libdev/dev.py +0 -0
- {libdev-0.84 → libdev-0.86}/libdev/doc.py +0 -0
- {libdev-0.84 → libdev-0.86}/libdev/fin.py +0 -0
- {libdev-0.84 → libdev-0.86}/libdev/gen.py +0 -0
- {libdev-0.84 → libdev-0.86}/libdev/img.py +0 -0
- {libdev-0.84 → libdev-0.86}/libdev/lang.py +0 -0
- {libdev-0.84 → libdev-0.86}/libdev/log.py +0 -0
- {libdev-0.84 → libdev-0.86}/libdev/num.py +0 -0
- {libdev-0.84 → libdev-0.86}/libdev/req.py +0 -0
- {libdev-0.84 → libdev-0.86}/libdev/s3.py +0 -0
- {libdev-0.84 → libdev-0.86}/libdev.egg-info/SOURCES.txt +0 -0
- {libdev-0.84 → libdev-0.86}/libdev.egg-info/dependency_links.txt +0 -0
- {libdev-0.84 → libdev-0.86}/libdev.egg-info/requires.txt +0 -0
- {libdev-0.84 → libdev-0.86}/libdev.egg-info/top_level.txt +0 -0
- {libdev-0.84 → libdev-0.86}/setup.cfg +0 -0
- {libdev-0.84 → libdev-0.86}/setup.py +0 -0
- {libdev-0.84 → libdev-0.86}/tests/test_cfg.py +0 -0
- {libdev-0.84 → libdev-0.86}/tests/test_check.py +0 -0
- {libdev-0.84 → libdev-0.86}/tests/test_codes.py +0 -0
- {libdev-0.84 → libdev-0.86}/tests/test_dev.py +0 -0
- {libdev-0.84 → libdev-0.86}/tests/test_doc.py +0 -0
- {libdev-0.84 → libdev-0.86}/tests/test_gen.py +0 -0
- {libdev-0.84 → libdev-0.86}/tests/test_img.py +0 -0
- {libdev-0.84 → libdev-0.86}/tests/test_lang.py +0 -0
- {libdev-0.84 → libdev-0.86}/tests/test_log.py +0 -0
- {libdev-0.84 → libdev-0.86}/tests/test_num.py +0 -0
- {libdev-0.84 → libdev-0.86}/tests/test_req.py +0 -0
|
@@ -78,7 +78,8 @@ def encrypt(number, length=5):
|
|
|
78
78
|
encoded_str = _int_to_custom_base(number)
|
|
79
79
|
# Calculate checksum and append to the end
|
|
80
80
|
checksum = _get_checksum(encoded_str)
|
|
81
|
-
encoded_str
|
|
81
|
+
if encoded_str != checksum:
|
|
82
|
+
encoded_str += checksum
|
|
82
83
|
# Add random characters to the beginning to meet the desired length
|
|
83
84
|
while len(encoded_str) < length:
|
|
84
85
|
random_char = random.choice(ALPHABET)
|
|
@@ -108,4 +109,4 @@ def decrypt(encoded_str):
|
|
|
108
109
|
candidate = encoded_str[i:]
|
|
109
110
|
if _get_checksum(candidate) == checksum:
|
|
110
111
|
return _custom_base_to_int(candidate)
|
|
111
|
-
|
|
112
|
+
return _custom_base_to_int(checksum)
|
|
@@ -38,6 +38,19 @@ DAYS_OF_WEEK = (
|
|
|
38
38
|
)
|
|
39
39
|
|
|
40
40
|
|
|
41
|
+
def to_tz(hours):
|
|
42
|
+
"""
|
|
43
|
+
Create a timezone object with the specified offset in hours.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
hours (int): The timezone offset in hours (e.g., 3 for UTC+3 or -5 for UTC-5).
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
datetime.timezone: A timezone object with the specified offset.
|
|
50
|
+
"""
|
|
51
|
+
return datetime.timezone(datetime.timedelta(hours=hours))
|
|
52
|
+
|
|
53
|
+
|
|
41
54
|
def get_time(data=None, template="%d.%m.%Y %H:%M:%S", tz=0):
|
|
42
55
|
"""Get time from timestamp"""
|
|
43
56
|
|
|
@@ -54,6 +67,11 @@ def get_time(data=None, template="%d.%m.%Y %H:%M:%S", tz=0):
|
|
|
54
67
|
return time.strftime(template, time.gmtime(data + tz * 3600))
|
|
55
68
|
|
|
56
69
|
|
|
70
|
+
def get_date(data=None, template="%d.%m.%Y", tz=0):
|
|
71
|
+
"""Get date from timestamp"""
|
|
72
|
+
return get_time(data, template, tz)
|
|
73
|
+
|
|
74
|
+
|
|
57
75
|
def decode_time(data=None, template="%d.%m.%Y %H:%M:%S", tz=0):
|
|
58
76
|
"""Get timestamp from time"""
|
|
59
77
|
|
|
@@ -72,6 +90,11 @@ def decode_time(data=None, template="%d.%m.%Y %H:%M:%S", tz=0):
|
|
|
72
90
|
return int(data.timestamp())
|
|
73
91
|
|
|
74
92
|
|
|
93
|
+
def decode_date(data=None, template="%d.%m.%Y", tz=0):
|
|
94
|
+
"""Get timestamp from date"""
|
|
95
|
+
return decode_time(data, template, tz)
|
|
96
|
+
|
|
97
|
+
|
|
75
98
|
# pylint: disable=too-many-branches,too-many-statements
|
|
76
99
|
def parse_time(data: str, tz=0):
|
|
77
100
|
"""Parse time"""
|
|
@@ -239,3 +262,99 @@ def format_delta(sec, short=False, locale="en"):
|
|
|
239
262
|
delta += " seconds"
|
|
240
263
|
|
|
241
264
|
return delta
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
def get_midnight(timestamp=None, tz=0):
|
|
268
|
+
"""
|
|
269
|
+
Get the start of the day (midnight) for a given timestamp in a specified timezone.
|
|
270
|
+
|
|
271
|
+
Args:
|
|
272
|
+
timestamp (float): The original timestamp (in seconds since epoch).
|
|
273
|
+
tz_offset_hours (int): The timezone offset in hours (e.g., 3 for UTC+3).
|
|
274
|
+
|
|
275
|
+
Returns:
|
|
276
|
+
float: The timestamp for the start of the day (midnight) in the specified timezone.
|
|
277
|
+
"""
|
|
278
|
+
if timestamp is None:
|
|
279
|
+
timestamp = time.time()
|
|
280
|
+
dt_local = datetime.datetime.fromtimestamp(timestamp, tz=to_tz(tz))
|
|
281
|
+
start_day = dt_local.replace(hour=0, minute=0, second=0, microsecond=0)
|
|
282
|
+
return int(start_day.timestamp())
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
def get_month_start(timestamp=None, tz=0):
|
|
286
|
+
"""
|
|
287
|
+
Get the start of the month (midnight on the first day of the month) for a given timestamp in a specified timezone.
|
|
288
|
+
|
|
289
|
+
Args:
|
|
290
|
+
timestamp (float): The original timestamp (in seconds since epoch). Defaults to the current time if None.
|
|
291
|
+
tz (int): The timezone offset in hours (e.g., 3 for UTC+3).
|
|
292
|
+
|
|
293
|
+
Returns:
|
|
294
|
+
float: The timestamp for the start of the month in the specified timezone.
|
|
295
|
+
"""
|
|
296
|
+
if timestamp is None:
|
|
297
|
+
timestamp = time.time()
|
|
298
|
+
dt_local = datetime.datetime.fromtimestamp(timestamp, tz=to_tz(tz))
|
|
299
|
+
start_month = dt_local.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
|
|
300
|
+
return int(start_month.timestamp())
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
def get_next_day(timestamp=None, tz=0):
|
|
304
|
+
"""
|
|
305
|
+
Get the start of the next day (midnight) for a given timestamp in a specified timezone.
|
|
306
|
+
|
|
307
|
+
Args:
|
|
308
|
+
timestamp (float): The original timestamp (in seconds since epoch). Defaults to the current time if None.
|
|
309
|
+
tz (int): The timezone offset in hours (e.g., 3 for UTC+3).
|
|
310
|
+
|
|
311
|
+
Returns:
|
|
312
|
+
float: The timestamp for the start of the next day (midnight) in the specified timezone.
|
|
313
|
+
"""
|
|
314
|
+
if timestamp is None:
|
|
315
|
+
timestamp = time.time()
|
|
316
|
+
dt_local = datetime.datetime.fromtimestamp(timestamp, tz=to_tz(tz))
|
|
317
|
+
next_day = (dt_local + datetime.timedelta(days=1)).replace(
|
|
318
|
+
hour=0, minute=0, second=0, microsecond=0
|
|
319
|
+
)
|
|
320
|
+
return int(next_day.timestamp())
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
def get_next_month(timestamp=None, tz=0):
|
|
324
|
+
"""
|
|
325
|
+
Get the start of the next month (midnight on the first day of the next month) for a given timestamp in a specified timezone.
|
|
326
|
+
|
|
327
|
+
Args:
|
|
328
|
+
timestamp (float): The original timestamp (in seconds since epoch). Defaults to the current time if None.
|
|
329
|
+
tz (int): The timezone offset in hours (e.g., 3 for UTC+3).
|
|
330
|
+
|
|
331
|
+
Returns:
|
|
332
|
+
float: The timestamp for the start of the next month in the specified timezone.
|
|
333
|
+
"""
|
|
334
|
+
|
|
335
|
+
if timestamp is None:
|
|
336
|
+
timestamp = time.time()
|
|
337
|
+
|
|
338
|
+
dt_local = datetime.datetime.fromtimestamp(timestamp, tz=to_tz(tz))
|
|
339
|
+
|
|
340
|
+
if dt_local.month == 12:
|
|
341
|
+
next_month = dt_local.replace(
|
|
342
|
+
year=dt_local.year + 1,
|
|
343
|
+
month=1,
|
|
344
|
+
day=1,
|
|
345
|
+
hour=0,
|
|
346
|
+
minute=0,
|
|
347
|
+
second=0,
|
|
348
|
+
microsecond=0,
|
|
349
|
+
)
|
|
350
|
+
else:
|
|
351
|
+
next_month = dt_local.replace(
|
|
352
|
+
month=dt_local.month + 1,
|
|
353
|
+
day=1,
|
|
354
|
+
hour=0,
|
|
355
|
+
minute=0,
|
|
356
|
+
second=0,
|
|
357
|
+
microsecond=0,
|
|
358
|
+
)
|
|
359
|
+
|
|
360
|
+
return int(next_month.timestamp())
|
|
@@ -3,9 +3,9 @@ from libdev.crypt import encrypt, decrypt
|
|
|
3
3
|
|
|
4
4
|
def test_cfg_json():
|
|
5
5
|
assert encrypt(None) == None
|
|
6
|
-
assert encrypt(0)[-
|
|
7
|
-
assert encrypt(0, length=0) == "
|
|
8
|
-
assert encrypt(0, length=10)[-
|
|
6
|
+
assert encrypt(0)[-1:] == "0"
|
|
7
|
+
assert encrypt(0, length=0) == "0"
|
|
8
|
+
assert encrypt(0, length=10)[-1:] == "0"
|
|
9
9
|
assert decrypt(encrypt(0, length=15)) == 0
|
|
10
10
|
assert decrypt(encrypt(123, length=15)) == 123
|
|
11
11
|
for i in range(0, 1000):
|
|
File without changes
|
|
@@ -4,7 +4,18 @@ https://www.epochconverter.com/
|
|
|
4
4
|
|
|
5
5
|
import datetime
|
|
6
6
|
|
|
7
|
-
from libdev.time import
|
|
7
|
+
from libdev.time import (
|
|
8
|
+
get_time,
|
|
9
|
+
get_date,
|
|
10
|
+
decode_time,
|
|
11
|
+
decode_date,
|
|
12
|
+
parse_time,
|
|
13
|
+
format_delta,
|
|
14
|
+
get_midnight,
|
|
15
|
+
get_month_start,
|
|
16
|
+
get_next_day,
|
|
17
|
+
get_next_month,
|
|
18
|
+
)
|
|
8
19
|
|
|
9
20
|
|
|
10
21
|
def test_get_time():
|
|
@@ -22,6 +33,10 @@ def test_get_time():
|
|
|
22
33
|
)
|
|
23
34
|
|
|
24
35
|
|
|
36
|
+
def test_get_date():
|
|
37
|
+
assert get_date(1641061152.4) == "01.01.2022"
|
|
38
|
+
|
|
39
|
+
|
|
25
40
|
def test_decode_time():
|
|
26
41
|
assert decode_time("") == None
|
|
27
42
|
assert decode_time("01.01.2022 21:19:12", tz=3) == 1641061152
|
|
@@ -29,6 +44,10 @@ def test_decode_time():
|
|
|
29
44
|
assert decode_time("2024-10-07", "%Y-%m-%d", 4) == 1728244800
|
|
30
45
|
|
|
31
46
|
|
|
47
|
+
def test_decode_date():
|
|
48
|
+
assert decode_date("01.01.2022", tz=3) == 1640984400
|
|
49
|
+
|
|
50
|
+
|
|
32
51
|
def test_parse_time():
|
|
33
52
|
assert parse_time("07.10.1998", tz=3) == 907707600
|
|
34
53
|
assert parse_time("7.10.1998 7:00:00") == 907743600
|
|
@@ -88,3 +107,24 @@ def test_format_delta_short():
|
|
|
88
107
|
assert format_delta(181, short=True, locale="ru") == "3мин"
|
|
89
108
|
assert format_delta(18000, short=True, locale="ru") == "5ч"
|
|
90
109
|
assert format_delta(1814400, short=True, locale="ru") == "21д"
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def test_get_midnight():
|
|
113
|
+
assert get_midnight(1721597607.049283) == 1721520000
|
|
114
|
+
assert get_midnight(1721597607, tz=3) == 1721595600
|
|
115
|
+
assert get_midnight(1704056399, tz=3) == 1703970000
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def test_get_month_start():
|
|
119
|
+
assert get_month_start(1704060061.049283) == 1701388800
|
|
120
|
+
assert get_month_start(1704060061, tz=3) == 1704056400
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def test_get_next_day():
|
|
124
|
+
assert get_next_day(1704060061) == 1704067200
|
|
125
|
+
assert get_next_day(1704060061, tz=3) == 1704142800
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def test_get_next_month():
|
|
129
|
+
assert get_next_month(1703980800) == 1704067200
|
|
130
|
+
assert get_next_month(1703970000, tz=3) == 1704056400
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|