diff --git a/swh/search/query_language/grammar.js b/swh/search/query_language/grammar.js --- a/swh/search/query_language/grammar.js +++ b/swh/search/query_language/grammar.js @@ -122,9 +122,9 @@ isoDateTime: $ => { const dateRegex = (/\d{4}[-]\d{2}[-]\d{2}/).source const dateTimeSepRegex = (/(\s|T)*/).source - const timeRegex = (/(\d{2}:\d{2}(:\d{2}(\.\d{6})?)?)?/).source - const timezoneRegex = (/(\+\d{2}:\d{2}|Z)?/).source - return new RegExp(dateRegex + dateTimeSepRegex + timeRegex + timezoneRegex) + const timeRegex = (/\d{2}:\d{2}(:\d{2}(\.\d{6})?)?/).source + const timezoneRegex = (/\+\d{2}:\d{2}|Z/).source + return new RegExp(`${dateRegex}(${dateTimeSepRegex}${timeRegex}(${timezoneRegex})?)?`) }, string: $ => choice(wrapWith($.stringContent, ["'", '"']), $.singleWord), diff --git a/swh/search/tests/test_elasticsearch.py b/swh/search/tests/test_elasticsearch.py --- a/swh/search/tests/test_elasticsearch.py +++ b/swh/search/tests/test_elasticsearch.py @@ -17,15 +17,15 @@ from .test_search import CommonSearchTest now = datetime.now(tz=timezone.utc).isoformat() -now_minus_5_hours = (datetime.now(tz=timezone.utc) - timedelta(hours=5)).isoformat() -now_plus_5_hours = (datetime.now(tz=timezone.utc) + timedelta(hours=5)).isoformat() +now_minus_5_days = (datetime.now(tz=timezone.utc) - timedelta(days=5)).isoformat() +now_plus_5_days = (datetime.now(tz=timezone.utc) + timedelta(days=5)).isoformat() ORIGINS = [ { "url": "http://foobar.1.com", "nb_visits": 1, - "last_visit_date": now_minus_5_hours, - "last_eventful_visit_date": now_minus_5_hours, + "last_visit_date": now_minus_5_days, + "last_eventful_visit_date": now_minus_5_days, }, { "url": "http://foobar.2.com", @@ -36,14 +36,14 @@ { "url": "http://foobar.3.com", "nb_visits": 3, - "last_visit_date": now_plus_5_hours, - "last_eventful_visit_date": now_minus_5_hours, + "last_visit_date": now_plus_5_days, + "last_eventful_visit_date": now_minus_5_days, }, { "url": "http://barbaz.4.com", "nb_visits": 3, - "last_visit_date": now_plus_5_hours, - "last_eventful_visit_date": now_minus_5_hours, + "last_visit_date": now_plus_5_days, + "last_eventful_visit_date": now_minus_5_days, }, ] @@ -184,6 +184,58 @@ "http://foobar.3.com", } + def test_search_ql_datetimes(self): + self.search.origin_update(ORIGINS) + self.search.flush() + + now_minus_5_minutes = ( + datetime.now(tz=timezone.utc) - timedelta(minutes=5) + ).isoformat() + now_plus_5_minutes = ( + datetime.now(tz=timezone.utc) + timedelta(minutes=5) + ).isoformat() + + results = { + r["url"] + for r in self.search.origin_search( + query=( + f"last_visit < {now_minus_5_minutes} " + f"or last_visit > {now_plus_5_minutes}" + ) + ).results + } + assert results == { + "http://foobar.1.com", + "http://foobar.3.com", + "http://barbaz.4.com", + } + + def test_search_ql_dates(self): + self.search.origin_update(ORIGINS) + self.search.flush() + + now_minus_2_days = ( + (datetime.now(tz=timezone.utc) - timedelta(days=2)).date().isoformat() + ) + now_plus_2_days = ( + (datetime.now(tz=timezone.utc) + timedelta(days=2)).date().isoformat() + ) + + results = { + r["url"] + for r in self.search.origin_search( + query=( + f"last_visit < {now_minus_2_days} " + f"or last_visit > {now_plus_2_days}" + ) + ).results + } + assert results == { + "http://foobar.1.com", + "http://foobar.3.com", + "http://barbaz.4.com", + } + def test_search_ql_visited(self): self.search.origin_update( [ @@ -191,8 +243,8 @@ "url": "http://foobar.1.com", "has_visits": True, "nb_visits": 1, - "last_visit_date": now_minus_5_hours, - "last_eventful_visit_date": now_minus_5_hours, + "last_visit_date": now_minus_5_days, + "last_eventful_visit_date": now_minus_5_days, }, {"url": "http://foobar.2.com",}, {"url": "http://foobar.3.com", "has_visits": False,}, diff --git a/swh/search/tests/test_translator.py b/swh/search/tests/test_translator.py --- a/swh/search/tests/test_translator.py +++ b/swh/search/tests/test_translator.py @@ -306,6 +306,22 @@ _test_results(query, expected) +def test_visit_date_range(): + query = "last_visit >= 2020-01-01 and last_visit < 2021-01-01" + expected = { + "filters": { + "bool": { + "must": [ + {"range": {"last_visit_date": {"gte": "2020-01-01"}}}, + {"range": {"last_visit_date": {"lt": "2021-01-01"}}}, + ] + } + }, + } + + _test_results(query, expected) + + def test_last_eventful_visit_not_equal_to_filter(): query = "last_visit != 2020-01-01" expected = {