Skip to content

Commit

Permalink
Add function to convert duration string to int
Browse files Browse the repository at this point in the history
  • Loading branch information
bennybp committed Jan 8, 2025
1 parent bf839b2 commit 3e86b5d
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 1 deletion.
32 changes: 31 additions & 1 deletion qcportal/qcportal/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from qcportal.utils import chunk_iterable, seconds_to_hms, is_included
from qcportal.utils import chunk_iterable, seconds_to_hms, duration_to_seconds, is_included


def test_chunk_iterable():
Expand Down Expand Up @@ -29,6 +29,36 @@ def test_seconds_to_hms():
assert seconds_to_hms(3670.12) == "01:01:10.12"


def test_duration_to_seconds():
assert duration_to_seconds(0) == 0
assert duration_to_seconds("0") == 0
assert duration_to_seconds(17) == 17
assert duration_to_seconds("17") == 17

assert duration_to_seconds("17s") == 17
assert duration_to_seconds("70s") == 70
assert duration_to_seconds("8m17s") == 497
assert duration_to_seconds("80m72s") == 4872
assert duration_to_seconds("3h8m17s") == 11297
assert duration_to_seconds("03h08m07s") == 11287
assert duration_to_seconds("03h08m070s") == 11350
assert duration_to_seconds("9d03h08m070s") == 788950

assert duration_to_seconds("9d") == 777600
assert duration_to_seconds("10m") == 600
assert duration_to_seconds("90m") == 5400
assert duration_to_seconds("04h") == 14400
assert duration_to_seconds("4h5s") == 14405
assert duration_to_seconds("1d9s") == 86409

assert duration_to_seconds("8:17") == 497
assert duration_to_seconds("80:72") == 4872
assert duration_to_seconds("3:8:17") == 11297
assert duration_to_seconds("03:08:07") == 11287
assert duration_to_seconds("03:08:070") == 11350
assert duration_to_seconds("9:03:08:07") == 788950


def test_is_included():
assert is_included("test", None, None, True) is True
assert is_included("test", None, None, False) is False
Expand Down
32 changes: 32 additions & 0 deletions qcportal/qcportal/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import json
import logging
import math
import re
import time
from contextlib import contextmanager, redirect_stderr, redirect_stdout
from hashlib import sha256
Expand Down Expand Up @@ -261,6 +262,37 @@ def seconds_to_hms(seconds: Union[float, int]) -> str:
return f"{hours:02d}:{minutes:02d}:{seconds+fraction:02.2f}"


def duration_to_seconds(s: Union[int, str]) -> int:
"""
Parses a string in dd:hh:mm:ss or 1d2h3m4s to an integer number of seconds
"""

# Is already an int
if isinstance(s, int):
return s

# Plain number of seconds (as a string)
if s.isdigit():
return int(s)

# Handle dd:hh:mm:ss format
if ":" in s:
parts = list(map(int, s.split(":")))
while len(parts) < 4: # Pad missing parts with zeros
parts.insert(0, 0)
days, hours, minutes, seconds = parts
return days * 86400 + hours * 3600 + minutes * 60 + seconds

# Handle format like 3d4h7m10s
pattern = re.compile(r"(?:(\d+)d)?(?:(\d+)h)?(?:(\d+)m)?(?:(\d+)s)?")
match = pattern.fullmatch(s)
if not match:
raise ValueError(f"Invalid duration format: {s}")

days, hours, minutes, seconds = map(lambda x: int(x) if x else 0, match.groups())
return days * 86400 + hours * 3600 + minutes * 60 + seconds


def recursive_normalizer(value: Any, digits: int = 10, lowercase: bool = True) -> Any:
"""
Prepare a structure for hashing by lowercasing all values and round all floats
Expand Down

0 comments on commit 3e86b5d

Please sign in to comment.