1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2026-02-04 07:51:50 +00:00
community.general/plugins/filter/time.py
2025-11-01 13:46:53 +01:00

147 lines
4.1 KiB
Python

# Copyright (c) 2020, René Moser <mail@renemoser.net>
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import annotations
import re
from ansible.errors import AnsibleFilterError
UNIT_FACTORS = {
"ms": [],
"s": [1000],
"m": [1000, 60],
"h": [1000, 60, 60],
"d": [1000, 60, 60, 24],
"w": [1000, 60, 60, 24, 7],
"mo": [1000, 60, 60, 24, 30],
"y": [1000, 60, 60, 24, 365],
}
UNIT_TO_SHORT_FORM = {
"millisecond": "ms",
"msec": "ms",
"msecond": "ms",
"sec": "s",
"second": "s",
"hour": "h",
"min": "m",
"minute": "m",
"day": "d",
"week": "w",
"month": "mo",
"year": "y",
}
def multiply(factors):
result = 1
for factor in factors:
result = result * factor
return result
def to_time_unit(human_time, unit="ms", **kwargs):
"""Return a time unit from a human readable string"""
# No need to handle 0
if human_time == "0":
return 0
unit_to_short_form = UNIT_TO_SHORT_FORM
unit_factors = UNIT_FACTORS
unit = unit_to_short_form.get(unit.rstrip("s"), unit)
if unit not in unit_factors:
raise AnsibleFilterError(
(
f"to_time_unit() can not convert to the following unit: {unit}. Available units (singular or plural):"
f"{', '.join(unit_to_short_form.keys())}. Available short units: {', '.join(unit_factors.keys())}"
)
)
if "year" in kwargs:
unit_factors["y"] = unit_factors["y"][:-1] + [kwargs.pop("year")]
if "month" in kwargs:
unit_factors["mo"] = unit_factors["mo"][:-1] + [kwargs.pop("month")]
if kwargs:
raise AnsibleFilterError(f"to_time_unit() got unknown keyword arguments: {', '.join(kwargs.keys())}")
result = 0
for h_time_string in human_time.split():
res = re.match(r"(-?\d+)(\w+)", h_time_string)
if not res:
raise AnsibleFilterError(f"to_time_unit() can not interpret following string: {human_time}")
h_time_int = int(res.group(1))
h_time_unit = res.group(2)
h_time_unit = unit_to_short_form.get(h_time_unit.rstrip("s"), h_time_unit)
if h_time_unit not in unit_factors:
raise AnsibleFilterError(f"to_time_unit() can not interpret following string: {human_time}")
time_in_milliseconds = h_time_int * multiply(unit_factors[h_time_unit])
result += time_in_milliseconds
return round(result / multiply(unit_factors[unit]), 12)
def to_milliseconds(human_time, **kwargs):
"""Return milli seconds from a human readable string"""
return to_time_unit(human_time, "ms", **kwargs)
def to_seconds(human_time, **kwargs):
"""Return seconds from a human readable string"""
return to_time_unit(human_time, "s", **kwargs)
def to_minutes(human_time, **kwargs):
"""Return minutes from a human readable string"""
return to_time_unit(human_time, "m", **kwargs)
def to_hours(human_time, **kwargs):
"""Return hours from a human readable string"""
return to_time_unit(human_time, "h", **kwargs)
def to_days(human_time, **kwargs):
"""Return days from a human readable string"""
return to_time_unit(human_time, "d", **kwargs)
def to_weeks(human_time, **kwargs):
"""Return weeks from a human readable string"""
return to_time_unit(human_time, "w", **kwargs)
def to_months(human_time, **kwargs):
"""Return months from a human readable string"""
return to_time_unit(human_time, "mo", **kwargs)
def to_years(human_time, **kwargs):
"""Return years from a human readable string"""
return to_time_unit(human_time, "y", **kwargs)
class FilterModule:
"""Ansible time jinja2 filters"""
def filters(self):
filters = {
"to_time_unit": to_time_unit,
"to_milliseconds": to_milliseconds,
"to_seconds": to_seconds,
"to_minutes": to_minutes,
"to_hours": to_hours,
"to_days": to_days,
"to_weeks": to_weeks,
"to_months": to_months,
"to_years": to_years,
}
return filters