onekit 4.0.0__tar.gz → 4.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: onekit
3
- Version: 4.0.0
3
+ Version: 4.1.0
4
4
  Summary: All-in-One Python Kit.
5
5
  License: BSD 3-Clause
6
6
  Keywords: onekit
@@ -22,7 +22,7 @@ requires-python = ">=3.11"
22
22
  dependencies = []
23
23
 
24
24
  [tool.poetry]
25
- version = "4.0.0"
25
+ version = "4.1.0"
26
26
 
27
27
  [project.optional-dependencies]
28
28
  base = [
@@ -9,9 +9,7 @@ from onekit import pythonkit as pk
9
9
  __all__ = (
10
10
  "ColumnNotFoundError",
11
11
  "InvalidChoiceError",
12
- "InvalidDateRangeWarning",
13
12
  "OnekitError",
14
- "OnekitWarning",
15
13
  "RowCountMismatchError",
16
14
  "RowValueMismatchError",
17
15
  "SchemaMismatchError",
@@ -141,11 +139,3 @@ class SchemaMismatchError(OnekitError):
141
139
  num_diff = sum(c == "|" for c in msg.splitlines()[1])
142
140
  self.message = pk.concat_strings(os.linesep, f"{num_diff=}", msg)
143
141
  super().__init__(self.message)
144
-
145
-
146
- class OnekitWarning(UserWarning):
147
- """A base class for onekit warnings."""
148
-
149
-
150
- class InvalidDateRangeWarning(OnekitWarning):
151
- """Warning for when a date range is provided in reverse order but is corrected."""
@@ -3,7 +3,6 @@ import datetime as dt
3
3
  import itertools
4
4
  import math
5
5
  import operator
6
- import warnings
7
6
  from contextlib import ContextDecorator
8
7
  from typing import (
9
8
  Generator,
@@ -18,6 +17,7 @@ from onekit import pythonkit as pk
18
17
 
19
18
  __all__ = (
20
19
  "DateRange",
20
+ "ElapsedTime",
21
21
  "create_date_range",
22
22
  "date_ago",
23
23
  "date_ahead",
@@ -35,10 +35,39 @@ __all__ = (
35
35
  "weekday",
36
36
  )
37
37
 
38
- from onekit.exception import (
39
- InvalidChoiceError,
40
- InvalidDateRangeWarning,
41
- )
38
+ from onekit.exception import InvalidChoiceError
39
+
40
+
41
+ class ElapsedTime(NamedTuple):
42
+ """Represents an immutable, human-readable format for elapsed time.
43
+
44
+ See Also
45
+ --------
46
+ date_diff : Function to compute the date difference between two dates.
47
+
48
+ Examples
49
+ --------
50
+ >>> from onekit.timekit import ElapsedTime
51
+ >>> et = ElapsedTime(years=0, months=0, weeks=0, days=6)
52
+ >>> et
53
+ ElapsedTime(years=0, months=0, weeks=0, days=6)
54
+ >>> str(et)
55
+ '0y 0m 0w 6d'
56
+ """
57
+
58
+ years: int
59
+ months: int
60
+ weeks: int
61
+ days: int
62
+
63
+ def __str__(self) -> str:
64
+ return pk.concat_strings(
65
+ " ",
66
+ f"{self.years}y",
67
+ f"{self.months}m",
68
+ f"{self.weeks}w",
69
+ f"{self.days}d",
70
+ )
42
71
 
43
72
 
44
73
  class DateRange(NamedTuple):
@@ -64,16 +93,16 @@ class DateRange(NamedTuple):
64
93
  >>> dr
65
94
  DateRange(min_date=datetime.date(2025, 6, 1), max_date=datetime.date(2025, 6, 3))
66
95
 
67
- >>> print(dr)
68
- date range from 2025-06-01 to 2025-06-03 - 3 days in total - difference 0y 0m 0w 2d
96
+ >>> str(dr)
97
+ 'DateRange(2025-06-01, 2025-06-03) - 3 days in total - elapsed time 0y 0m 0w 2d'
69
98
 
70
- >>> dr.difference
71
- '0y 0m 0w 2d'
99
+ >>> dr.elapsed_time
100
+ ElapsedTime(years=0, months=0, weeks=0, days=2)
72
101
 
73
- >>> dr.difference_in_days
102
+ >>> dr.elapsed_days
74
103
  2
75
104
 
76
- >>> dr.difference_in_years
105
+ >>> dr.elapsed_years
77
106
  0
78
107
 
79
108
  >>> dr.number_of_days
@@ -88,38 +117,29 @@ class DateRange(NamedTuple):
88
117
 
89
118
  def __str__(self) -> str:
90
119
  n = self.number_of_days
91
- number_of_days = "1 day" if n == 1 else f"{pk.num_to_str(n)} days"
92
- return pk.concat_strings(
93
- " ",
94
- "date range",
95
- f"from {date_to_str(self.min_date)}",
96
- f"to {date_to_str(self.max_date)}",
97
- f"- {number_of_days} in total",
98
- f"- difference {self.difference}",
120
+ return (
121
+ "{cls_name}({min_date}, {max_date}) - {n} in total - elapsed time {x}"
122
+ ).format(
123
+ cls_name=self.__class__.__name__,
124
+ min_date=date_to_str(self.min_date),
125
+ max_date=date_to_str(self.max_date),
126
+ n="1 day" if n == 1 else f"{pk.num_to_str(n)} days",
127
+ x=str(self.elapsed_time),
99
128
  )
100
129
 
101
130
  @property
102
- def difference(self) -> str:
103
- """Compute duration between the min and max date."""
104
- delta = relativedelta(self.max_date, self.min_date)
105
- weeks = delta.days // 7
106
- remaining_days = delta.days % 7
107
- return pk.concat_strings(
108
- " ",
109
- f"{delta.years}y",
110
- f"{delta.months}m",
111
- f"{weeks}w",
112
- f"{remaining_days}d",
113
- )
131
+ def elapsed_time(self) -> ElapsedTime:
132
+ """Compute the elapsed time between the min and max date (max exclusive)."""
133
+ return date_diff(self.min_date, self.max_date, unit=None)
114
134
 
115
135
  @property
116
- def difference_in_days(self) -> int:
117
- """Compute the difference in days between the min and max date."""
136
+ def elapsed_days(self) -> int:
137
+ """Compute the elapsed days between the min and max date (max exclusive)."""
118
138
  return date_diff(self.min_date, self.max_date, unit="days")
119
139
 
120
140
  @property
121
- def difference_in_years(self) -> int:
122
- """Compute the difference in years between the min and max date."""
141
+ def elapsed_years(self) -> int:
142
+ """Compute the elapsed years between the min and max date (max exclusive)."""
123
143
  return date_diff(self.min_date, self.max_date, unit="years")
124
144
 
125
145
  @property
@@ -161,11 +181,6 @@ def create_date_range(min_date: dt.date, max_date: dt.date, /) -> DateRange:
161
181
  DateRange
162
182
  An immutable date range object with `min_date <= max_date`.
163
183
 
164
- Warns
165
- -----
166
- InvalidDateRangeWarning
167
- If the input dates are in reverse order (`min_date > max_date`) and are swapped.
168
-
169
184
  See Also
170
185
  --------
171
186
  DateRange : The immutable date range object returned by this factory.
@@ -182,17 +197,12 @@ def create_date_range(min_date: dt.date, max_date: dt.date, /) -> DateRange:
182
197
  >>> tk.create_date_range(dt.date(2025, 6, 1), dt.date(2025, 6, 1))
183
198
  DateRange(min_date=datetime.date(2025, 6, 1), max_date=datetime.date(2025, 6, 1))
184
199
 
185
- >>> # dates provided in reverse order
186
- >>> dr = tk.create_date_range(dt.date(2025, 6, 7), dt.date(2025, 6, 1))
187
- >>> # a warning "dates provided in reverse order - swapping" is printed to stderr
188
- >>> dr
200
+ >>> # dates provided in reverse order are automatically swapped
201
+ >>> tk.create_date_range(dt.date(2025, 6, 7), dt.date(2025, 6, 1))
189
202
  DateRange(min_date=datetime.date(2025, 6, 1), max_date=datetime.date(2025, 6, 7))
190
203
  """
191
204
  if min_date > max_date:
192
205
  min_date, max_date = max_date, min_date
193
- message = "dates provided in reverse order - swapping"
194
- warnings.warn(message, InvalidDateRangeWarning)
195
-
196
206
  return DateRange(min_date, max_date)
197
207
 
198
208
 
@@ -279,8 +289,18 @@ def date_count_forward(ref_date: dt.date, /) -> Generator:
279
289
 
280
290
 
281
291
  # noinspection PyUnreachableCode
282
- def date_diff(min_date: dt.date, max_date: dt.date, /, *, unit: str = "days") -> int:
283
- """Compute difference between dates.
292
+ def date_diff(
293
+ min_date: dt.date,
294
+ max_date: dt.date,
295
+ /,
296
+ *,
297
+ unit: str | None = None,
298
+ ) -> ElapsedTime | int:
299
+ """Compute date difference between the min and max date (max exclusive).
300
+
301
+ See Also
302
+ --------
303
+ ElapsedTime : The immutable, human-readable object for elapsed time.
284
304
 
285
305
  Examples
286
306
  --------
@@ -289,19 +309,35 @@ def date_diff(min_date: dt.date, max_date: dt.date, /, *, unit: str = "days") ->
289
309
  >>> d1 = dt.date(2024, 7, 1)
290
310
  >>> d2 = dt.date(2024, 7, 7)
291
311
 
292
- >>> tk.date_diff(d1, d1)
312
+ >>> dd = tk.date_diff(d1, d2, unit=None)
313
+ >>> dd
314
+ ElapsedTime(years=0, months=0, weeks=0, days=6)
315
+ >>> str(dd)
316
+ '0y 0m 0w 6d'
317
+
318
+ >>> tk.date_diff(d1, d1, unit="days")
293
319
  0
294
320
 
295
- >>> tk.date_diff(d1, d2)
321
+ >>> tk.date_diff(d1, d2, unit="days")
296
322
  6
297
323
 
298
- >>> tk.date_diff(d2, d1)
324
+ >>> tk.date_diff(d2, d1, unit="days")
299
325
  -6
300
326
 
301
327
  >>> tk.date_diff(d1, d2, unit="years")
302
328
  0
303
329
  """
330
+ choices = [None, "days", "years"]
304
331
  match unit:
332
+ case None:
333
+ delta = relativedelta(max_date, min_date)
334
+ return ElapsedTime(
335
+ years=delta.years,
336
+ months=delta.months,
337
+ weeks=delta.days // 7,
338
+ days=delta.days % 7,
339
+ )
340
+
305
341
  case "days":
306
342
  return (max_date - min_date).days
307
343
 
@@ -309,7 +345,7 @@ def date_diff(min_date: dt.date, max_date: dt.date, /, *, unit: str = "days") ->
309
345
  return relativedelta(max_date, min_date).years
310
346
 
311
347
  case _:
312
- raise InvalidChoiceError(value=unit, choices=["days", "years"])
348
+ raise InvalidChoiceError(unit, choices)
313
349
 
314
350
 
315
351
  # noinspection PyTypeChecker
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