Skip to content

Instantly share code, notes, and snippets.

@thorwhalen
Created October 25, 2019 20:06
Show Gist options
  • Save thorwhalen/82603b6df28bc842741b421668d2a83f to your computer and use it in GitHub Desktop.
Save thorwhalen/82603b6df28bc842741b421668d2a83f to your computer and use it in GitHub Desktop.
A util to get a number of seconds from a (flexible) string description of a duration using day, hour, minutes, and seconds units.
import time
import re
p = re.compile('[\d\.]+')
seconds_for_unit = {
'd': 60 * 60 * 24,
'h': 60 * 60,
'm': 60,
's': 1
}
def time_spec_to_seconds(time_spec: str) -> float:
"""A flexible way to get a time (duration) in seconds, from a string.
How flexible? Well, the string needs to interleave numbers and words, and the first letter of the word needs
to be d (day), h (hour), m (minute), or s (second). The function will ignore the rest.
Args:
time_spec: The string specifying the time
Returns: A duration, float, in seconds.
>>> assert time_spec_to_seconds('5 minutes') == 300.0
>>> assert time_spec_to_seconds('1heure 1mn 1 secondi') == 3600 + 60 + 1 # only the first letter of the unit counts
>>> assert time_spec_to_seconds('72m109.7s') == 4429.7 # numbers don't have a limit and can use decimals
>>> assert time_spec_to_seconds('3h 12mn42 seconds') == 11562.0
"""
requested_time = None
keys = list(map(str.strip, p.split(time_spec)))
vals = list(map(float, p.findall(time_spec)))
if keys[0] == '':
keys = keys[1:]
if len(keys) >= 1 and len(vals) >= 1:
duration_spec = list(zip(vals, keys))
requested_time = 0
for val, unit in duration_spec:
seconds_to_add = val * seconds_for_unit.get(unit[0], None)
if seconds_to_add is None:
raise ValueError(
f"Malformated time string (should use units d, h, m, and s): {time_spec}")
requested_time += seconds_to_add
return requested_time
def now_minus_spec_to_utc_seconds(now_minus_spec: str) -> float:
"""Get the UTC time of now minus some duration.
Input must start with a dash (that is, the minus symbol "-") and then describe a duration,
with days, hours, minutes, and/or seconds.
Args:
now_minus_spec: A string starting with "-" and then interleaving numbers and time units
Returns: A UTC seconds float
Examples:
now_minus_spec_to_utc_seconds('- 1 hour 2 mn 43s')
"""
assert now_minus_spec.startswith('-'), "String should start with '-'"
return time.time() - time_spec_to_seconds(now_minus_spec[1:])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment