diff options
| author | robot-piglet <[email protected]> | 2025-06-10 11:56:30 +0300 |
|---|---|---|
| committer | robot-piglet <[email protected]> | 2025-06-10 12:22:18 +0300 |
| commit | c7979a01f4770552c335e2251158561d1267b1ca (patch) | |
| tree | 44ec838be6485eb4701a785722917f99954db484 /contrib/python/durationpy | |
| parent | 4904e8018684e2a3d6148f7a0fc9075db7798961 (diff) | |
Intermediate changes
commit_hash:8f651cd5d60bd83ae5ee0d24c330ef405b82a372
Diffstat (limited to 'contrib/python/durationpy')
| -rw-r--r-- | contrib/python/durationpy/.dist-info/METADATA | 11 | ||||
| -rw-r--r-- | contrib/python/durationpy/.dist-info/top_level.txt | 1 | ||||
| -rw-r--r-- | contrib/python/durationpy/LICENSE | 7 | ||||
| -rw-r--r-- | contrib/python/durationpy/README.md | 29 | ||||
| -rw-r--r-- | contrib/python/durationpy/durationpy/__init__.py | 2 | ||||
| -rw-r--r-- | contrib/python/durationpy/durationpy/__init__.pyi | 6 | ||||
| -rw-r--r-- | contrib/python/durationpy/durationpy/duration.py | 149 | ||||
| -rw-r--r-- | contrib/python/durationpy/durationpy/py.typed | 0 | ||||
| -rw-r--r-- | contrib/python/durationpy/ya.make | 25 |
9 files changed, 230 insertions, 0 deletions
diff --git a/contrib/python/durationpy/.dist-info/METADATA b/contrib/python/durationpy/.dist-info/METADATA new file mode 100644 index 00000000000..a88d559b7c2 --- /dev/null +++ b/contrib/python/durationpy/.dist-info/METADATA @@ -0,0 +1,11 @@ +Metadata-Version: 2.1 +Name: durationpy +Version: 0.10 +Summary: Module for converting between datetime.timedelta and Go's Duration strings. +Home-page: https://github.com/icholy/durationpy +Download-URL: https://github.com/icholy/durationpy/tarball/0.10 +Author: Ilia Choly +Author-email: [email protected] +License: MIT +License-File: LICENSE + diff --git a/contrib/python/durationpy/.dist-info/top_level.txt b/contrib/python/durationpy/.dist-info/top_level.txt new file mode 100644 index 00000000000..3b6d235abac --- /dev/null +++ b/contrib/python/durationpy/.dist-info/top_level.txt @@ -0,0 +1 @@ +durationpy diff --git a/contrib/python/durationpy/LICENSE b/contrib/python/durationpy/LICENSE new file mode 100644 index 00000000000..e14d50a7612 --- /dev/null +++ b/contrib/python/durationpy/LICENSE @@ -0,0 +1,7 @@ +Copyright 2017 Ilia Choly + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/contrib/python/durationpy/README.md b/contrib/python/durationpy/README.md new file mode 100644 index 00000000000..2c01d9266bc --- /dev/null +++ b/contrib/python/durationpy/README.md @@ -0,0 +1,29 @@ +# durationpy + +> Module for converting between `datetime.timedelta` and Go's Duration strings. + +### Install + +``` sh +$ pip install durationpy +``` + + +### Parse + +* `ns` - nanoseconds +* `us` - microseconds +* `ms` - millisecond +* `s` - second +* `m` - minute +* `h` - hour + +``` py +# parse +td = durationpy.from_str("4h3m2s1ms") + +# format +durationpy.to_str(td) +``` + +**Note:** nanosecond precision is lost because `datetime.timedelta` uses microsecond resolution. diff --git a/contrib/python/durationpy/durationpy/__init__.py b/contrib/python/durationpy/durationpy/__init__.py new file mode 100644 index 00000000000..70c043cd6b9 --- /dev/null +++ b/contrib/python/durationpy/durationpy/__init__.py @@ -0,0 +1,2 @@ +# -*- coding: UTF-8 -*- +from .duration import to_str, from_str, DurationError diff --git a/contrib/python/durationpy/durationpy/__init__.pyi b/contrib/python/durationpy/durationpy/__init__.pyi new file mode 100644 index 00000000000..3879d1ad7d5 --- /dev/null +++ b/contrib/python/durationpy/durationpy/__init__.pyi @@ -0,0 +1,6 @@ +import datetime + +def from_str(duration: str) -> datetime.timedelta: ... +def to_str(delta: datetime.timedelta, extended: bool = ...) -> str: ... + +class DurationError(ValueError): ... diff --git a/contrib/python/durationpy/durationpy/duration.py b/contrib/python/durationpy/durationpy/duration.py new file mode 100644 index 00000000000..1e4b27dd33d --- /dev/null +++ b/contrib/python/durationpy/durationpy/duration.py @@ -0,0 +1,149 @@ +# -*- coding: UTF-8 -*- + +import re +import datetime + +_nanosecond_size = 1 +_microsecond_size = 1000 * _nanosecond_size +_millisecond_size = 1000 * _microsecond_size +_second_size = 1000 * _millisecond_size +_minute_size = 60 * _second_size +_hour_size = 60 * _minute_size +_day_size = 24 * _hour_size +_week_size = 7 * _day_size +_month_size = 30 * _day_size +_year_size = 365 * _day_size + +units = { + "ns": _nanosecond_size, + "us": _microsecond_size, + "µs": _microsecond_size, + "μs": _microsecond_size, + "ms": _millisecond_size, + "s": _second_size, + "m": _minute_size, + "h": _hour_size, + "d": _day_size, + "w": _week_size, + "mm": _month_size, + "y": _year_size, +} + +_duration_re = re.compile(r'([\d\.]+)([a-zµμ]+)') + + +class DurationError(ValueError): + """duration error""" + + +def from_str(duration): + """Parse a duration string to a datetime.timedelta""" + + original = duration + + if duration in ("0", "+0", "-0"): + return datetime.timedelta() + + sign = 1 + if duration and duration[0] in '+-': + if duration[0] == '-': + sign = -1 + duration = duration[1:] + + matches = list(_duration_re.finditer(duration)) + if not matches: + raise DurationError("Invalid duration {}".format(original)) + if matches[0].start() != 0 or matches[-1].end() != len(duration): + raise DurationError( + 'Extra chars at start or end of duration {}'.format(original)) + + total = 0 + for match in matches: + value, unit = match.groups() + if unit not in units: + raise DurationError( + "Unknown unit {} in duration {}".format(unit, original)) + try: + total += float(value) * units[unit] + except Exception: + raise DurationError( + "Invalid value {} in duration {}".format(value, original)) + + microseconds = total / _microsecond_size + return datetime.timedelta(microseconds=sign * microseconds) + +def to_str(delta, extended=False): + """Format a datetime.timedelta to a duration string""" + + total_seconds = delta.total_seconds() + sign = "-" if total_seconds < 0 else "" + nanoseconds = round(abs(total_seconds * _second_size), 0) + + if abs(total_seconds) < 1: + result_str = _to_str_small(nanoseconds, extended) + else: + result_str = _to_str_large(nanoseconds, extended) + + return "{}{}".format(sign, result_str) + + +def _to_str_small(nanoseconds, extended): + + result_str = "" + + if not nanoseconds: + return "0" + + milliseconds = int(nanoseconds / _millisecond_size) + if milliseconds: + nanoseconds -= _millisecond_size * milliseconds + result_str += "{:g}ms".format(milliseconds) + + microseconds = int(nanoseconds / _microsecond_size) + if microseconds: + nanoseconds -= _microsecond_size * microseconds + result_str += "{:g}us".format(microseconds) + + if nanoseconds: + result_str += "{:g}ns".format(nanoseconds) + + return result_str + + +def _to_str_large(nanoseconds, extended): + + result_str = "" + + if extended: + + years = int(nanoseconds / _year_size) + if years: + nanoseconds -= _year_size * years + result_str += "{:g}y".format(years) + + months = int(nanoseconds / _month_size) + if months: + nanoseconds -= _month_size * months + result_str += "{:g}mm".format(months) + + days = int(nanoseconds / _day_size) + if days: + nanoseconds -= _day_size * days + result_str += "{:g}d".format(days) + + hours = int(nanoseconds / _hour_size) + if hours: + nanoseconds -= _hour_size * hours + result_str += "{:g}h".format(hours) + + minutes = int(nanoseconds / _minute_size) + if minutes: + nanoseconds -= _minute_size * minutes + result_str += "{:g}m".format(minutes) + + seconds = float(nanoseconds) / float(_second_size) + if seconds: + nanoseconds -= _second_size * seconds + result_str += "{:g}s".format(seconds) + + return result_str diff --git a/contrib/python/durationpy/durationpy/py.typed b/contrib/python/durationpy/durationpy/py.typed new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/contrib/python/durationpy/durationpy/py.typed diff --git a/contrib/python/durationpy/ya.make b/contrib/python/durationpy/ya.make new file mode 100644 index 00000000000..e5c00aff909 --- /dev/null +++ b/contrib/python/durationpy/ya.make @@ -0,0 +1,25 @@ +# Generated by devtools/yamaker (pypi). + +PY3_LIBRARY() + +VERSION(0.10) + +LICENSE(MIT) + +NO_LINT() + +PY_SRCS( + TOP_LEVEL + durationpy/__init__.py + durationpy/__init__.pyi + durationpy/duration.py +) + +RESOURCE_FILES( + PREFIX contrib/python/durationpy/ + .dist-info/METADATA + .dist-info/top_level.txt + durationpy/py.typed +) + +END() |
