From b70051d851808b77211270a2fc953fa3c4bdd6c7 Mon Sep 17 00:00:00 2001 From: Samuel Johnson Date: Mon, 5 Jan 2026 16:44:24 -0500 Subject: [PATCH 1/5] update invalid date docs --- resources/schema/Operator.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/resources/schema/Operator.md b/resources/schema/Operator.md index 4b0b650b4..1baadd2a5 100644 --- a/resources/schema/Operator.md +++ b/resources/schema/Operator.md @@ -563,9 +563,11 @@ Date check ### invalid_date -Date check +The operator performs date validation against complete and partial dates with uncertainty in the following order: -> BRTHDTC is invalid +1. Attempts to parse using [dateutil.parser.isoparse()](https://dateutil.readthedocs.io/en/stable/parser.html) +2. If parsing fails and the string contains uncertainty indicators (`/`, `--`, `-:`), validates against an extended ISO 8601 dates regex pattern +3. If parsing succeeds, dates are still validated against the regex pattern. ```yaml - name: "BRTHDTC" From d2b344cdd926700d6d3a3c95fd645b3237f6e361 Mon Sep 17 00:00:00 2001 From: Samuel Johnson Date: Thu, 15 Jan 2026 15:18:05 -0500 Subject: [PATCH 2/5] same date, diff precision --- cdisc_rules_engine/check_operators/helpers.py | 16 +---- .../test_date_comparison_checks.py | 58 +++++++++++++++++++ 2 files changed, 61 insertions(+), 13 deletions(-) diff --git a/cdisc_rules_engine/check_operators/helpers.py b/cdisc_rules_engine/check_operators/helpers.py index e6bc63ce8..085cb48d9 100644 --- a/cdisc_rules_engine/check_operators/helpers.py +++ b/cdisc_rules_engine/check_operators/helpers.py @@ -203,8 +203,8 @@ def get_common_precision(dt1: str, dt2: str) -> DatePrecision | None: def get_date_component(component: str, date_string: str): date = get_date(date_string) try: - return getattr(date, DatePrecision[component].name) - except (KeyError, ValueError): + return getattr(date, component) + except AttributeError: return date @@ -255,7 +255,7 @@ def get_date(date_string: str): def is_complete_date(date_string: str) -> bool: try: datetime.fromisoformat(date_string) - except Exception as e: + except Exception: try: datetime.fromisoformat(date_string.replace("Z", "+00:00")) except Exception as e: @@ -264,10 +264,6 @@ def is_complete_date(date_string: str) -> bool: f"traceback: {traceback.format_exc()}" ) return False - logger.error( - f"Error with date parsing: {str(e)}, " - f"traceback: {traceback.format_exc()}" - ) return True return True @@ -361,12 +357,6 @@ def _compare_with_inferred_precision( result = operator_func(truncated_target, truncated_comparator) - if truncated_target == truncated_comparator: - if target_precision and comparator_precision: - if target_precision.value > comparator_precision.value: - return operator_func(get_date(target), get_date(comparator)) - return result - return result diff --git a/tests/unit/test_check_operators/test_date_comparison_checks.py b/tests/unit/test_check_operators/test_date_comparison_checks.py index e2e4e2a16..8dc3348dc 100644 --- a/tests/unit/test_check_operators/test_date_comparison_checks.py +++ b/tests/unit/test_check_operators/test_date_comparison_checks.py @@ -893,3 +893,61 @@ def test_auto_precision_operators( params["date_component"] = date_component result = operator_method(params) assert result.equals(df.convert_to_series([expected_result])) + + +@pytest.mark.parametrize( + "target,comparator,dataset_type,expected_result", + [ + ( + {"target": ["2013-01-23T05:10"]}, + "2013-01-23", + PandasDataset, + [False], + ), + ( + {"target": ["2013-01-23T05:10"]}, + "2013-01-23", + DaskDataset, + [False], + ), + ( + {"target": ["2025-01-10T14:30:45"]}, + "2025-01-10", + PandasDataset, + [False], + ), + ( + {"target": ["2025-01-10T00:00:00"]}, + "2025-01-10", + DaskDataset, + [False], + ), + ( + {"target": ["2025-01-11T05:10"]}, + "2025-01-10", + PandasDataset, + [True], + ), + ( + {"target": ["2025-01-10"]}, + "2025", + DaskDataset, + [False], + ), + ( + {"target": ["2025-01-15T12:30"]}, + "2025-01", + PandasDataset, + [False], + ), + ], +) +def test_date_greater_than_same_date_different_precision( + target, comparator, dataset_type, expected_result +): + df = dataset_type.from_dict(target) + dataframe_type = DataframeType({"value": df}) + result = dataframe_type.date_greater_than( + {"target": "target", "comparator": comparator} + ) + assert result.equals(df.convert_to_series(expected_result)) From 0cd9eafc52a2f8946a212525ce926e019c8ac43b Mon Sep 17 00:00:00 2001 From: Samuel Johnson Date: Thu, 15 Jan 2026 15:29:07 -0500 Subject: [PATCH 3/5] fix tests --- .../unit/test_check_operators/test_date_comparison_checks.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/test_check_operators/test_date_comparison_checks.py b/tests/unit/test_check_operators/test_date_comparison_checks.py index 8dc3348dc..db29a963d 100644 --- a/tests/unit/test_check_operators/test_date_comparison_checks.py +++ b/tests/unit/test_check_operators/test_date_comparison_checks.py @@ -380,7 +380,7 @@ def test_date_less_than_date_components( }, "comparator", PandasDataset, - [True, True, True, True, True], + [True, False, False, False, False], ), ( { @@ -394,7 +394,7 @@ def test_date_less_than_date_components( }, "1997-07", DaskDataset, - [True, False, False, False, False], + [True, True, True, True, True], ), ], ) From 2b249617ac45d630b811ea3980c42a8b18a5e7e1 Mon Sep 17 00:00:00 2001 From: Samuel Johnson Date: Thu, 15 Jan 2026 15:30:15 -0500 Subject: [PATCH 4/5] fix tests --- tests/unit/test_check_operators/test_date_comparison_checks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/test_check_operators/test_date_comparison_checks.py b/tests/unit/test_check_operators/test_date_comparison_checks.py index db29a963d..89223300e 100644 --- a/tests/unit/test_check_operators/test_date_comparison_checks.py +++ b/tests/unit/test_check_operators/test_date_comparison_checks.py @@ -380,7 +380,7 @@ def test_date_less_than_date_components( }, "comparator", PandasDataset, - [True, False, False, False, False], + [True, True, True, True, True], ), ( { From 7701eee590b7832fab6796e80908b0911b963e31 Mon Sep 17 00:00:00 2001 From: Samuel Johnson Date: Thu, 15 Jan 2026 15:55:15 -0500 Subject: [PATCH 5/5] tests --- tests/unit/test_check_operators/test_date_comparison_checks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/test_check_operators/test_date_comparison_checks.py b/tests/unit/test_check_operators/test_date_comparison_checks.py index 89223300e..43764151a 100644 --- a/tests/unit/test_check_operators/test_date_comparison_checks.py +++ b/tests/unit/test_check_operators/test_date_comparison_checks.py @@ -525,7 +525,7 @@ def test_date_less_than_or_equal_to_date_components( }, "1997-07", PandasDataset, - [False, True, True, True, True], + [False, False, False, False, False], ), ], )