From 4b1e3d40619efd5e6c91698535d7859c9da0265c Mon Sep 17 00:00:00 2001 From: Fizzlepoof Date: Fri, 22 May 2026 09:27:46 -0500 Subject: [PATCH] Handle Weissman day and overnight times --- automation/bin/kitchenowl_recipe_import.py | 11 ++++++++--- home/doris-kitchen/app/services/recipe_importer.py | 11 ++++++++--- home/doris-kitchen/tests/test_tagging.py | 3 +++ 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/automation/bin/kitchenowl_recipe_import.py b/automation/bin/kitchenowl_recipe_import.py index c4cc340..98b95c5 100755 --- a/automation/bin/kitchenowl_recipe_import.py +++ b/automation/bin/kitchenowl_recipe_import.py @@ -296,9 +296,10 @@ def enrich_recipe_node_from_dom(recipe_node: dict[str, Any], html: str) -> dict[ DURATION_RE = re.compile(r'^P(?:T(?:(?P\d+)H)?(?:(?P\d+)M)?(?:(?P\d+)S)?)?$') TEXT_DURATION_PART_RE = re.compile( - r'(?P\d+(?:\.\d+)?)\s*(?Phours?|hrs?|hr|minutes?|mins?|min|seconds?|secs?|sec|s)\b', + r'(?P\d+(?:\.\d+)?)\s*(?Pdays?|day|hours?|hrs?|hr|minutes?|mins?|min|seconds?|secs?|sec|s)\b', re.IGNORECASE, ) +OVERNIGHT_RE = re.compile(r'\bovernight\b', re.IGNORECASE) def parse_duration_minutes(value: Any) -> int | None: @@ -319,17 +320,21 @@ def parse_duration_minutes(value: Any) -> int | None: total = hours * 60 + minutes + (1 if seconds >= 30 else 0) return total or None textual_matches = list(TEXT_DURATION_PART_RE.finditer(value)) - if textual_matches: + overnight_count = len(OVERNIGHT_RE.findall(value)) + if textual_matches or overnight_count: total_minutes = 0.0 for part in textual_matches: amount = float(part.group('value')) unit = part.group('unit').lower() - if unit.startswith(('hour', 'hr')): + if unit.startswith('day'): + total_minutes += amount * 24 * 60 + elif unit.startswith(('hour', 'hr')): total_minutes += amount * 60 elif unit.startswith(('minute', 'min')): total_minutes += amount else: total_minutes += amount / 60 + total_minutes += overnight_count * 12 * 60 rounded = int(total_minutes + 0.5) return rounded or None num = re.search(r'(\d+)', value) diff --git a/home/doris-kitchen/app/services/recipe_importer.py b/home/doris-kitchen/app/services/recipe_importer.py index 07c0f75..f8216eb 100644 --- a/home/doris-kitchen/app/services/recipe_importer.py +++ b/home/doris-kitchen/app/services/recipe_importer.py @@ -21,9 +21,10 @@ STOPWORDS = {"fresh", "large", "small", "medium", "optional", "to", "taste", "fo TAG_KEYS = ("recipeCategory", "recipeCuisine", "keywords") DURATION_RE = re.compile(r"^P(?:T(?:(?P\d+)H)?(?:(?P\d+)M)?(?:(?P\d+)S)?)?$") TEXT_DURATION_PART_RE = re.compile( - r"(?P\d+(?:\.\d+)?)\s*(?Phours?|hrs?|hr|minutes?|mins?|min|seconds?|secs?|sec|s)\b", + r"(?P\d+(?:\.\d+)?)\s*(?Pdays?|day|hours?|hrs?|hr|minutes?|mins?|min|seconds?|secs?|sec|s)\b", re.IGNORECASE, ) +OVERNIGHT_RE = re.compile(r"\bovernight\b", re.IGNORECASE) class ScriptExtractor(HTMLParser): @@ -415,17 +416,21 @@ def parse_duration_minutes(value: Any) -> int | None: total = hours * 60 + minutes + (1 if seconds >= 30 else 0) return total or None textual_matches = list(TEXT_DURATION_PART_RE.finditer(text)) - if textual_matches: + overnight_count = len(OVERNIGHT_RE.findall(text)) + if textual_matches or overnight_count: total_minutes = 0.0 for part in textual_matches: amount = float(part.group("value")) unit = part.group("unit").lower() - if unit.startswith(("hour", "hr")): + if unit.startswith("day"): + total_minutes += amount * 24 * 60 + elif unit.startswith(("hour", "hr")): total_minutes += amount * 60 elif unit.startswith(("minute", "min")): total_minutes += amount else: total_minutes += amount / 60 + total_minutes += overnight_count * 12 * 60 rounded = int(total_minutes + 0.5) return rounded or None number = re.search(r"(\d+)", text) diff --git a/home/doris-kitchen/tests/test_tagging.py b/home/doris-kitchen/tests/test_tagging.py index d18de37..493788a 100644 --- a/home/doris-kitchen/tests/test_tagging.py +++ b/home/doris-kitchen/tests/test_tagging.py @@ -13,6 +13,9 @@ class TaggingTests(unittest.TestCase): def test_textual_durations_cover_weissman_style_time_strings(self): self.assertEqual(parse_duration_minutes('1 hr, 15 min'), 75) self.assertEqual(parse_duration_minutes('45 min + 12 hrs'), 765) + self.assertEqual(parse_duration_minutes('1 day + 30 min'), 1470) + self.assertEqual(parse_duration_minutes('1 hr + overnight'), 780) + self.assertEqual(parse_duration_minutes('1 hr 30 min + overnight'), 810) self.assertEqual(parse_duration_minutes('30 minutes'), 30) self.assertEqual(parse_duration_minutes('90 sec'), 2)