I needed a way to convert seconds to a human readable interval/format like 1w instead of 604800, or 3D18h3m54s instead of 324234, but I also wanted to be able to parse the result back in seconds.
"""Convert seconds to human readable interval back and forth."""
from collections import OrderedDict
import re
interval_dict = OrderedDict([("Y", 365*86400), # 1 year
("M", 30*86400), # 1 month
("W", 7*86400), # 1 week
("D", 86400), # 1 day
("h", 3600), # 1 hour
("m", 60), # 1 minute
("s", 1)]) # 1 second
def seconds_to_human(seconds):
"""Convert seconds to human readable format like 1M.
:param seconds: Seconds to convert
:type seconds: int
:rtype: int
:return: Human readable string
"""
seconds = int(seconds)
string = ""
for unit, value in interval_dict.items():
subres = seconds / value
if subres:
seconds -= value * subres
string += str(subres) + unit
return string
def human_to_seconds(string):
"""Convert internal string like 1M, 1Y3M, 3W to seconds.
:type string: str
:param string: Interval string like 1M, 1W, 1M3W4h2s...
(s => seconds, m => minutes, h => hours, D => days, W => weeks, M => months, Y => Years).
:rtype: int
:return: The conversion in seconds of string.
"""
interval_exc = "Bad interval format for {0}".format(string)
interval_regex = re.compile("^(?P<value>[0-9]+)(?P<unit>[{0}])".format("".join(interval_dict.keys())))
seconds = 0
while string:
match = interval_regex.match(string)
if match:
value, unit = int(match.group("value")), match.group("unit")
if int(value) and unit in interval_dict:
seconds += value * interval_dict[unit]
string = string[match.end():]
else:
raise Exception(interval_exc)
else:
raise Exception(interval_exc)
return seconds
if __name__ == "__main__":
assert seconds_to_human(324234) == "3D18h3m54s"
assert human_to_seconds("3D18h3m54s") == 324234
assert seconds_to_human(365 * 86400) == "1Y"
assert human_to_seconds("1Y") == 365 * 86400
Let me know if you have any questions, ideas, or improvements !
Tip with Bitcoin
Tip me with Bitcoin and vote for this post!
Leave a comment