Fix `format_timedelta` function's parsing of negative timedeltas (#5740)
* Fix `format_timedelta` function's parsing of negative timedeltas. The entire timedelta can be negative. * Refactor to use a single timedelta regular expression. * Fix typo in `format_timedelta` function argument.
This commit is contained in:
Родитель
214d062b5b
Коммит
5a7d7985c1
|
@ -1,9 +1,9 @@
|
|||
"""This file contains custom filters for formatting data types in Jinja templates."""
|
||||
|
||||
import re
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from bigquery_etl import query_scheduling
|
||||
from bigquery_etl.query_scheduling.utils import TIMEDELTA_RE
|
||||
|
||||
|
||||
def format_schedule_interval(interval):
|
||||
|
@ -36,20 +36,18 @@ def format_date(date_string):
|
|||
|
||||
# based on https://stackoverflow.com/questions/4628122/how-to-construct-a
|
||||
# -timedelta-object-from-a-simple-string
|
||||
def format_timedelta(timdelta_string):
|
||||
def format_timedelta(timedelta_string):
|
||||
"""Format a timedelta object."""
|
||||
timedelta_regex = re.compile(
|
||||
r"^((?P<hours>-?\d+?)h)?((?P<minutes>-?\d+?)m)?((?P<seconds>-?\d+?)s)?$"
|
||||
)
|
||||
parts = timedelta_regex.match(timdelta_string)
|
||||
parts = TIMEDELTA_RE.match(timedelta_string)
|
||||
if not parts:
|
||||
return timdelta_string
|
||||
return timedelta_string
|
||||
|
||||
parts = parts.groupdict()
|
||||
is_negative = timedelta_string.startswith("-")
|
||||
time_params = {}
|
||||
for name, param in parts.items():
|
||||
if param:
|
||||
time_params[name] = int(param)
|
||||
time_params[name] = int(param) * (-1 if is_negative else 1)
|
||||
|
||||
return timedelta(**time_params)
|
||||
|
||||
|
|
|
@ -3,6 +3,10 @@
|
|||
import re
|
||||
from datetime import datetime
|
||||
|
||||
TIMEDELTA_RE = re.compile(
|
||||
r"^-?((?P<hours>\d+)h)?((?P<minutes>\d+)m)?((?P<seconds>\d+)s)?$"
|
||||
)
|
||||
|
||||
|
||||
def is_timedelta_string(s):
|
||||
"""
|
||||
|
@ -10,8 +14,7 @@ def is_timedelta_string(s):
|
|||
|
||||
Timedeltas in configs are specified like: 1h, 30m, 1h15m, ...
|
||||
"""
|
||||
timedelta_regex = re.compile(r"^-?(\d+h)?(\d+m)?(\d+s)?$")
|
||||
return timedelta_regex.match(s)
|
||||
return TIMEDELTA_RE.match(s)
|
||||
|
||||
|
||||
def validate_timedelta_string(s):
|
||||
|
|
|
@ -43,10 +43,15 @@ class TestFormatters:
|
|||
assert format_timedelta(123)
|
||||
|
||||
assert format_timedelta("1h") == datetime.timedelta(seconds=3600)
|
||||
assert format_timedelta("-1h") == datetime.timedelta(seconds=-3600)
|
||||
assert format_timedelta("15m") == datetime.timedelta(seconds=900)
|
||||
assert format_timedelta("-15m") == datetime.timedelta(seconds=-900)
|
||||
assert format_timedelta("1h15m") == datetime.timedelta(seconds=4500)
|
||||
assert format_timedelta("-1h15m") == datetime.timedelta(seconds=-4500)
|
||||
assert format_timedelta("1s") == datetime.timedelta(seconds=1)
|
||||
assert format_timedelta("-1s") == datetime.timedelta(seconds=-1)
|
||||
assert format_timedelta("1h1m1s") == datetime.timedelta(seconds=3661)
|
||||
assert format_timedelta("-1h1m1s") == datetime.timedelta(seconds=-3661)
|
||||
assert format_timedelta("1d1h1m1s") == "1d1h1m1s"
|
||||
|
||||
def test_format_optional_string(self):
|
||||
|
|
Загрузка…
Ссылка в новой задаче