diff --git a/content/code/2023-10-11-python-date-conversion.md b/content/code/2023-10-11-python-date-conversion.md index e5fb33e..d4887aa 100644 --- a/content/code/2023-10-11-python-date-conversion.md +++ b/content/code/2023-10-11-python-date-conversion.md @@ -8,9 +8,10 @@ I found myself wanting to convert a string to a duration (int), for some configu Something you can call like this: ```python -string_to_duration("1d", target="days") # returns 1 -string_to_duration("1d", target="hours") # returns 24 -string_to_duration("3m", target="hours") # returns 3 * 24 * 30 +string_to_duration("1d", target="days") +string_to_duration("1d", target="hours") +string_to_duration("3m", target="hours") +string_to_duration("3m", target="minutes") ``` The code : @@ -18,32 +19,42 @@ The code : ```python from typing import Literal - -def string_to_duration(value: str, target: Literal["days", "hours"]): - """Convert a string to a number of hours, or days""" +def string_to_duration(value: str, target: Literal["days", "hours", "minutes"]): + """Convert a string to a number of hours, days or minutes""" num = int("".join(filter(str.isdigit, value))) - if target == "hours": - reconvert = True + # It's not possible to convert from a smaller unit to a greater one: + # - hours and minutes cannot be converted to days + # - minutes cannot be converted to hours + if (target == "days" and ("h" in value or "m" in value.replace("mo", ""))) or ( + target == "hours" and "m" in value.replace("mo", "") + ): + msg = ( + "Durations cannot be converted from a smaller to a greater unit. " + f"(trying to convert '{value}' to {target})" + ) + raise ValueError(msg, value) + # Consider we're converting to minutes, do the eventual multiplication at the end. if "h" in value: - if target == "days": - raise ValueError("Invalid duration value", value) - num = num - reconvert = False + num = num * 60 elif "d" in value: - num = num + num = num * 60 * 24 elif "w" in value: - num = num * 7 - elif "m" in value: - num = num * 30 + num = num * 60 * 24 * 7 + elif "mo" in value: + num = num * 60 * 24 * 30 # considers 30d in a month elif "y" in value: - num = num * 365 + num = num * 60 * 24 * 365 + elif "m" in value: + num = num else: raise ValueError("Invalid duration value", value) - if target == "hours" and reconvert: - num = num * 24 + if target == "hours": + num = num / 60 + elif target == "days": + num = num / 60 / 24 return num ``` \ No newline at end of file