Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions apps/api/plane/tests/unit/utils/test_legacy_filter_converter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Copyright (c) 2023-present Plane Software, Inc. and contributors
# SPDX-License-Identifier: AGPL-3.0-only
# See the LICENSE file for details.

import pytest

from plane.utils.filters.converters import LegacyToRichFiltersConverter


@pytest.mark.unit
class TestLegacyToRichFiltersConverterDateOrdering:
"""
_convert_date_value must order date range bounds chronologically,
not lexicographically. See: https://github.com/makeplane/plane/issues/9567
"""

def setup_method(self):
self.converter = LegacyToRichFiltersConverter()

def test_non_iso_date_range_is_ordered_chronologically(self):
# '9/1/2023' (Sep 1) < '10/1/2023' (Oct 1) chronologically, but
# '10/1/2023' < '9/1/2023' lexicographically ('1' < '9').
# The old code used string min/max and produced a reversed range.
result = self.converter._convert_date_value(
"target_date",
["9/1/2023;after", "10/1/2023;before"],
)
assert result["target_date__range"] == "2023-09-01,2023-10-01"

def test_iso_date_range_still_works(self):
result = self.converter._convert_date_value(
"target_date",
["2023-09-01;after", "2023-12-31;before"],
)
assert result["target_date__range"] == "2023-09-01,2023-12-31"
9 changes: 7 additions & 2 deletions apps/api/plane/utils/filters/converters.py
Original file line number Diff line number Diff line change
Expand Up @@ -306,8 +306,13 @@ def _convert_date_value(self, field_name: str, values: List[str], strict: bool =
result = {}
if len(after_dates) == 1 and len(before_dates) == 1 and len(exact_dates) == 0:
# Simple range: one after and one before
start_date = min(after_dates[0], before_dates[0])
end_date = max(after_dates[0], before_dates[0])
# Parse to datetime objects so comparison is chronological, not lexicographic.
# String min/max only works for zero-padded ISO YYYY-MM-DD; other formats
# accepted by _validate_date (e.g. M/D/YYYY) would produce a reversed range.
after_date = dateutil_parse(after_dates[0]).date()
before_date = dateutil_parse(before_dates[0]).date()
start_date = min(after_date, before_date).isoformat()
end_date = max(after_date, before_date).isoformat()
self._add_rich_filter(result, field_name, "range", [start_date, end_date])
elif len(exact_dates) == 1 and len(after_dates) == 0 and len(before_dates) == 0:
# Single exact date
Expand Down