chronos-timetool 0.1.0__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.
- chronos_timetool-0.1.0/LICENSE +21 -0
- chronos_timetool-0.1.0/PKG-INFO +397 -0
- chronos_timetool-0.1.0/README.md +376 -0
- chronos_timetool-0.1.0/pyproject.toml +36 -0
- chronos_timetool-0.1.0/src/chronos/__init__.py +29 -0
- chronos_timetool-0.1.0/src/chronos/core.py +916 -0
- chronos_timetool-0.1.0/src/chronos/exceptions.py +36 -0
- chronos_timetool-0.1.0/src/chronos/packages.py +533 -0
- chronos_timetool-0.1.0/src/chronos/parser.py +261 -0
- chronos_timetool-0.1.0/src/chronos/py.typed +0 -0
- chronos_timetool-0.1.0/src/chronos/utils.py +270 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Pedro Antonio Rodrigues
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: chronos-timetool
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A Python library for quickly manipulating time and obtain time data.
|
|
5
|
+
Author-email: Pedro Antonio Rodrigues <pedro.a.rodrigues7@gmail.com>
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Keywords: chronos,datetime,time,timer,timetool,tool
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Requires-Python: >=3.9
|
|
16
|
+
Requires-Dist: babel>=2.10.0
|
|
17
|
+
Requires-Dist: parsedatetime>=2.6
|
|
18
|
+
Requires-Dist: python-dateutil>=2.8.2
|
|
19
|
+
Requires-Dist: pytz>=2022.1
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
# Chronos Timetool
|
|
24
|
+
|
|
25
|
+
**A Swiss Army knife for time manipulation in Python.**
|
|
26
|
+
|
|
27
|
+

|
|
28
|
+

|
|
29
|
+

|
|
30
|
+

|
|
31
|
+
|
|
32
|
+
Chronos is a comprehensive library designed to handle all your time-related needs: parsing, formatting, timezone management, business day calculations, humanized durations, performance profiling, and much more. It combines robust parsing engines, intuitive APIs, and extensive utilities to make working with dates and times effortless. The library and all classes are heavily typed, and completely secure to any task you'd need Chronos.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Table of Contents
|
|
37
|
+
|
|
38
|
+
- [Features](#features)
|
|
39
|
+
- [Installation](#installation)
|
|
40
|
+
- [Core Module (`core.py`)](#core-module-corepy)
|
|
41
|
+
- [Chronos Class](#chronos-class)
|
|
42
|
+
- [Countries Class](#countries-class)
|
|
43
|
+
- [Time Class](#time-class)
|
|
44
|
+
- [Parser Module (`parser.py`)](#parser-module-parserpy)
|
|
45
|
+
- [Utils Module (`utils.py`)](#utils-module-utilspy)
|
|
46
|
+
- [Packages & Exceptions](#packages--exceptions)
|
|
47
|
+
- [Examples](#examples)
|
|
48
|
+
- [Contributing](#contributing)
|
|
49
|
+
- [License](#license)
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Features
|
|
54
|
+
|
|
55
|
+
- ⏱ **High‑precision stopwatch** and function profiling decorators
|
|
56
|
+
- 🌍 **Country information** – get GMT/UTC offsets, locale formats, capitals, currencies
|
|
57
|
+
- 🧠 **Smart parsing** – accepts timestamps, ISO strings, regional formats, and even natural language (“next Friday”)
|
|
58
|
+
- 📅 **Business day calculations** – skip weekends and holidays
|
|
59
|
+
- 🗓 **Humanized time differences** (“3 days ago”, “in 2 hours”) with locale support
|
|
60
|
+
- 🕒 **Timezone‑aware** – work with UTC, GMT offsets, and DST detection
|
|
61
|
+
- 🔄 **Duration parsing** – convert “2h 30min” into seconds, minutes, etc.
|
|
62
|
+
- 📁 **Safe timestamp slugs** for file names and IDs
|
|
63
|
+
- 🔁 **Retry decorator** with exponential backoff
|
|
64
|
+
- 🖥 **Terminal utilities** – colorful ASCII art, countdowns, and clean output
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Installation
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
pip install chronos-timetool
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Chronos requires Python 3.8+ and depends on:
|
|
75
|
+
|
|
76
|
+
- `babel` – for locale‑aware formatting
|
|
77
|
+
- `python-dateutil` – for flexible parsing
|
|
78
|
+
- `pytz` – for timezone handling
|
|
79
|
+
- `countryinfo` – for offline country data
|
|
80
|
+
- `parsedatetime` – for natural language detection
|
|
81
|
+
|
|
82
|
+
These are automatically installed with the package.
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Core Module (`core.py`)
|
|
87
|
+
|
|
88
|
+
The heart of Chronos. It provides three main classes: `Chronos`, `Countries`, and `Time`.
|
|
89
|
+
|
|
90
|
+
### Chronos Class
|
|
91
|
+
|
|
92
|
+
Utility methods and decorators for everyday tasks.
|
|
93
|
+
|
|
94
|
+
#### `@Chronos.profile(verbose=True)`
|
|
95
|
+
|
|
96
|
+
Measures and prints the execution time of a function.
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
from chronos import Chronos
|
|
100
|
+
|
|
101
|
+
@Chronos.profile(verbose=True)
|
|
102
|
+
def heavy_computation():
|
|
103
|
+
# ... do work
|
|
104
|
+
return result
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
#### `@Chronos.retry(retries=3, delay=1.0, verbose=True)`
|
|
108
|
+
|
|
109
|
+
Automatically retries a function on exception.
|
|
110
|
+
|
|
111
|
+
```python
|
|
112
|
+
@Chronos.retry(retries=5, delay=2)
|
|
113
|
+
def fetch_api():
|
|
114
|
+
# network call
|
|
115
|
+
pass
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
#### `Chronos.countdown(seconds, message, show_prefix)`
|
|
119
|
+
|
|
120
|
+
Displays a clean countdown in the terminal.
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
Chronos.countdown(5, "Server starting", show_prefix=True)
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
#### `Chronos.sleep(seconds)`
|
|
127
|
+
|
|
128
|
+
A safe sleep wrapper that ensures a positive integer delay.
|
|
129
|
+
|
|
130
|
+
#### `Chronos.Stopwatch`
|
|
131
|
+
|
|
132
|
+
Context‑manager stopwatch with pause/resume and multiple units.
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
with Chronos.Stopwatch() as sw:
|
|
136
|
+
# do work
|
|
137
|
+
print(sw.elapsed(unit="ms")) # "123.456 ms"
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
### Countries Class
|
|
143
|
+
|
|
144
|
+
Retrieve geographical and timezone information for any country.
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
from chronos import Countries
|
|
148
|
+
|
|
149
|
+
jp = Countries("japan")
|
|
150
|
+
print(jp.get_GMT()) # "+9"
|
|
151
|
+
print(jp.get_UTC()) # "+9"
|
|
152
|
+
print(jp.get_FORMAT()) # "ja-JP"
|
|
153
|
+
print(jp.get_info()) # {'capital': 'Tokyo', 'currencies': ['JPY'], ...}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Supports country names (full or partial), alpha‑2 codes, alpha‑3 codes, and many language aliases.
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
### Time Class
|
|
161
|
+
|
|
162
|
+
The central class for time manipulation, localization, and calculations.
|
|
163
|
+
|
|
164
|
+
#### Instantiation with options
|
|
165
|
+
|
|
166
|
+
```python
|
|
167
|
+
from chronos import Time
|
|
168
|
+
|
|
169
|
+
# Default: UTC+0, en‑US, 24‑hour format
|
|
170
|
+
t = Time()
|
|
171
|
+
|
|
172
|
+
# Custom timezone, locale, and 12‑hour clock
|
|
173
|
+
t = Time(options={
|
|
174
|
+
"UTC": "+5:30", # India
|
|
175
|
+
"FORMAT": "hi-IN",
|
|
176
|
+
"AM_PM": True,
|
|
177
|
+
"BASE_TIME": "2026-01-01 12:00"
|
|
178
|
+
})
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Available options:
|
|
182
|
+
|
|
183
|
+
- `UTC` / `GMT` – offset string (e.g., `"+5:30"`) or float
|
|
184
|
+
- `FORMAT` – locale string (e.g., `"pt-BR"`)
|
|
185
|
+
- `LOCAL` – boolean; if `True`, uses local system timezone
|
|
186
|
+
- `AM_PM` – boolean; `True` for 12‑hour display
|
|
187
|
+
- `BASE_TIME` – any parseable date/time to use as reference
|
|
188
|
+
|
|
189
|
+
#### Key methods
|
|
190
|
+
|
|
191
|
+
- **`time()`** – returns the current (or base) datetime in the configured timezone.
|
|
192
|
+
- **`smart_parse(raw)`** – universal parser: handles timestamps, ISO, localized formats.
|
|
193
|
+
- **`is_expired(target, against=None)`** – checks if a date has passed.
|
|
194
|
+
- **`range(target)`** – difference between base and target in years, months, days, etc.
|
|
195
|
+
- **`calculate(years=0, months=0, ...)`** – add/subtract units from base time.
|
|
196
|
+
- **`humanize(against)`** – returns relative text like “2 days ago” (locale‑aware).
|
|
197
|
+
- **`age()`** – exact age from `BASE_TIME` to now.
|
|
198
|
+
- **`is_legal_age(limit=18)`** – checks if age >= limit.
|
|
199
|
+
- **Business day helpers** – `next_business_day()`, `next_business_days(n)`, `last_business_day_of_month()`.
|
|
200
|
+
- **`overlaps(start_A, end_A, start_B, end_B)`** – interval overlap check.
|
|
201
|
+
- **`is_weekend()`, `is_business_day()`** – boolean checks.
|
|
202
|
+
- **`start_of_day()`, `end_of_day()`** – trim to boundaries.
|
|
203
|
+
- **`to_iso()`, `to_rfc2822()`** – standard format outputs.
|
|
204
|
+
- **`is_dst(timezone)`, `is_ambiguous(timezone)`** – DST detection and ambiguity.
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## Parser Module (`parser.py`)
|
|
209
|
+
|
|
210
|
+
A standalone engine for parsing, converting, and transforming temporal data with extreme flexibility.
|
|
211
|
+
|
|
212
|
+
### `Parser._to_datetime(item)`
|
|
213
|
+
|
|
214
|
+
Internal but exposed as a robust entry point. Accepts:
|
|
215
|
+
|
|
216
|
+
- Python `datetime` objects
|
|
217
|
+
- Integers/floats (Unix timestamps, auto‑scaling milliseconds)
|
|
218
|
+
- Strings – ISO, regional, logs with embedded dates, and natural language (via fallback)
|
|
219
|
+
|
|
220
|
+
```python
|
|
221
|
+
from chronos.parser import Parser
|
|
222
|
+
|
|
223
|
+
dt = Parser._to_datetime("ERROR [2026-07-07 14:30:00] - crash") # returns datetime
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### `Parser.convert(item, to, gmt_shift=None)`
|
|
227
|
+
|
|
228
|
+
Transform any input into one of four formats:
|
|
229
|
+
|
|
230
|
+
- `"datetime"` – returns a `datetime` object
|
|
231
|
+
- `"posix"` – returns Unix timestamp (float)
|
|
232
|
+
- `"iso"` – returns ISO 8601 string
|
|
233
|
+
- `"dict"` – returns dictionary with `year`, `month`, `day`, `hour`, `minute`, `second`
|
|
234
|
+
|
|
235
|
+
Optionally apply a GMT shift on the fly.
|
|
236
|
+
|
|
237
|
+
```python
|
|
238
|
+
# From natural language to Unix timestamp
|
|
239
|
+
ts = Parser.convert("next monday", to="posix")
|
|
240
|
+
|
|
241
|
+
# Timestamp to ISO with +3 hours
|
|
242
|
+
iso = Parser.convert(1722000000, to="iso", gmt_shift=3)
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### `Parser.transform(years=0, months=0, ..., to="seconds", base_time=None)`
|
|
246
|
+
|
|
247
|
+
Converts a combination of time units into a single unit with calendar‑precision.
|
|
248
|
+
|
|
249
|
+
```python
|
|
250
|
+
# How many days in 2 years and 1 month?
|
|
251
|
+
days = Parser.transform(years=2, months=1, to="days") # ~761 days (leap years considered)
|
|
252
|
+
|
|
253
|
+
# Using a specific base (e.g., during a leap year)
|
|
254
|
+
days_feb = Parser.transform(months=1, to="days", base_time="2024-01-01") # 29
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### `Parser.parse_duration(duration_str, to="seconds", base_time=None)`
|
|
258
|
+
|
|
259
|
+
Parses human‑readable durations like `"2h 30min"` or `"1.5 days"` and returns the value in the requested unit.
|
|
260
|
+
|
|
261
|
+
```python
|
|
262
|
+
seconds = Parser.parse_duration("1d 12h") # 129600.0
|
|
263
|
+
minutes = Parser.parse_duration("2.5 hours", to="minutes") # 150.0
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### `Parser.detect(string, base_time=None)`
|
|
267
|
+
|
|
268
|
+
Uses `parsedatetime` to interpret natural language expressions relative to a given base time.
|
|
269
|
+
|
|
270
|
+
```python
|
|
271
|
+
dt = Parser.detect("in 2 weeks") # datetime 2 weeks from now
|
|
272
|
+
past = Parser.detect("3 days ago", base_time="2026-07-01") # 2026-06-28
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
## Utils Module (`utils.py`)
|
|
278
|
+
|
|
279
|
+
Helper functions for common tasks.
|
|
280
|
+
|
|
281
|
+
### `Utils.is_leap_year(item)`
|
|
282
|
+
|
|
283
|
+
Checks if a year (or date) is a leap year.
|
|
284
|
+
|
|
285
|
+
```python
|
|
286
|
+
from chronos.utils import Utils
|
|
287
|
+
|
|
288
|
+
u = Utils()
|
|
289
|
+
u.is_leap_year(2024) # True
|
|
290
|
+
u.is_leap_year("2023") # False
|
|
291
|
+
u.is_leap_year("2024-02-29") # True
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### `Utils.timestamp_slug(base_time=None, compact=False)`
|
|
295
|
+
|
|
296
|
+
Generates a clean timestamp string for file names or IDs.
|
|
297
|
+
|
|
298
|
+
```python
|
|
299
|
+
u.timestamp_slug() # "2026-07-08_14-30-15"
|
|
300
|
+
u.timestamp_slug(compact=True) # "20260708143015"
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### `Utils.days_in_month(month, year=None)`
|
|
304
|
+
|
|
305
|
+
Number of days in a given month (handles leap years).
|
|
306
|
+
|
|
307
|
+
```python
|
|
308
|
+
u.days_in_month(2, 2024) # 29
|
|
309
|
+
u.days_in_month(2, 2023) # 28
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### `Utils.quarter(item=None)` and `Utils.week_of_year(item=None)`
|
|
313
|
+
|
|
314
|
+
Return the fiscal quarter (1‑4) and ISO week number (1‑53) for any date.
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## Packages & Exceptions
|
|
319
|
+
|
|
320
|
+
- **`packages.py`** – contains constants, default values, unit mappings, country alpha‑3 codes, ASCII art alphabet, and a `Tools` class with rounding, type checking, and limit functions.
|
|
321
|
+
- **`exceptions.py`** – custom exceptions for clear error handling:
|
|
322
|
+
- `ParserErrorException`
|
|
323
|
+
- `HumanizerErrorException`
|
|
324
|
+
- `CountryCodeNotFoundException`
|
|
325
|
+
- `IsLeapYearValueErrorException`
|
|
326
|
+
- `TimestampSlugValueErrorException`
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
## Examples
|
|
331
|
+
|
|
332
|
+
### 1. Profile a function and retry on failure
|
|
333
|
+
|
|
334
|
+
```python
|
|
335
|
+
from chronos import Chronos, Time
|
|
336
|
+
|
|
337
|
+
@Chronos.profile(verbose=True)
|
|
338
|
+
@Chronos.retry(retries=3)
|
|
339
|
+
def fetch_data():
|
|
340
|
+
# simulate flaky API
|
|
341
|
+
pass
|
|
342
|
+
|
|
343
|
+
fetch_data()
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
### 2. Get business days between two dates
|
|
347
|
+
|
|
348
|
+
```python
|
|
349
|
+
from chronos import Time
|
|
350
|
+
|
|
351
|
+
t = Time(options={"BASE_TIME": "2026-07-01"})
|
|
352
|
+
next_three = t.next_business_days(3) # list of datetimes
|
|
353
|
+
last = t.last_business_day_of_month(holidays=["2026-07-04"])
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
### 3. Parse dirty log entries
|
|
357
|
+
|
|
358
|
+
```python
|
|
359
|
+
from chronos.parser import Parser
|
|
360
|
+
|
|
361
|
+
log = "ERROR [2026-07-07 14:30:00] - Disk full"
|
|
362
|
+
iso = Parser.convert(log, to="iso") # "2026-07-07T14:30:00"
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
### 4. Humanize a past event
|
|
366
|
+
|
|
367
|
+
```python
|
|
368
|
+
from chronos import Time
|
|
369
|
+
|
|
370
|
+
t = Time(options={"BASE_TIME": "2026-07-01 12:00"})
|
|
371
|
+
print(t.humanize(against="2026-07-01 11:30")) # "30 minutes ago"
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
### 5. Generate a safe filename
|
|
375
|
+
|
|
376
|
+
```python
|
|
377
|
+
from chronos.utils import Utils
|
|
378
|
+
|
|
379
|
+
u = Utils()
|
|
380
|
+
filename = f"backup_{u.timestamp_slug()}.sql"
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
---
|
|
384
|
+
|
|
385
|
+
## Contributing
|
|
386
|
+
|
|
387
|
+
Contributions are welcome! Please open an issue or pull request on [GitHub](https://github.com/DevPedroLab/chronos). Ensure code is well‑tested and follows the existing style.
|
|
388
|
+
|
|
389
|
+
---
|
|
390
|
+
|
|
391
|
+
## License
|
|
392
|
+
|
|
393
|
+
Chronos is released under the MIT License. See [LICENSE](LICENSE) for details.
|
|
394
|
+
|
|
395
|
+
---
|
|
396
|
+
|
|
397
|
+
**Made with ❤️ by [DevPedroLab](https://github.com/DevPedroLab)**
|