From 3c2e3e33e7970501cd062b5e4f4e0a53ad9f409d Mon Sep 17 00:00:00 2001 From: Arkadii Yakovets Date: Wed, 26 Apr 2023 03:59:31 -0700 Subject: [PATCH] fix(utils): evaluate date parser multiple holiday results correctly (#23685) --- requirements/base.txt | 3 +-- setup.py | 2 +- superset/utils/date_parser.py | 4 ++-- tests/unit_tests/utils/date_parser_tests.py | 22 +++++++++++++++++++++ 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/requirements/base.txt b/requirements/base.txt index 5e54e1e06d232..a8a61ef6e6e4d 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -130,7 +130,7 @@ hashids==1.3.1 # via apache-superset hijri-converter==2.2.4 # via holidays -holidays==0.17.2 +holidays==0.23 # via apache-superset humanize==3.11.0 # via apache-superset @@ -298,7 +298,6 @@ typing-extensions==4.4.0 # apache-superset # flask-limiter # limits - # rich urllib3==1.26.6 # via selenium vine==5.0.0 diff --git a/setup.py b/setup.py index 664d320b22e53..c63bd2104207e 100644 --- a/setup.py +++ b/setup.py @@ -96,7 +96,7 @@ def get_git_sha() -> str: "graphlib-backport", "gunicorn>=20.1.0; sys_platform != 'win32'", "hashids>=1.3.1, <2", - "holidays>=0.17.2, <0.18", + "holidays>=0.23, <0.24", "humanize", "isodate", "markdown>=3.0", diff --git a/superset/utils/date_parser.py b/superset/utils/date_parser.py index d23cd01de8664..7cdc23784a737 100644 --- a/superset/utils/date_parser.py +++ b/superset/utils/date_parser.py @@ -386,8 +386,8 @@ def eval(self) -> datetime: country = country.eval() if country else "US" holiday_lookup = country_holidays(country, years=[holiday_year], observed=False) - searched_result = holiday_lookup.get_named(holiday) - if len(searched_result) == 1: + searched_result = holiday_lookup.get_named(holiday, lookup="istartswith") + if len(searched_result) > 0: return dttm_from_timetuple(searched_result[0].timetuple()) raise ValueError( _("Unable to find such a holiday: [%(holiday)s]", holiday=holiday) diff --git a/tests/unit_tests/utils/date_parser_tests.py b/tests/unit_tests/utils/date_parser_tests.py index f3c8b6968077b..fb0fe07d29902 100644 --- a/tests/unit_tests/utils/date_parser_tests.py +++ b/tests/unit_tests/utils/date_parser_tests.py @@ -60,10 +60,14 @@ def mock_parse_human_datetime(s: str) -> Optional[datetime]: return datetime(2017, 4, 7) elif s in ["5 days", "5 days ago"]: return datetime(2016, 11, 2) + elif s == "2000-01-01T00:00:00": + return datetime(2000, 1, 1) elif s == "2018-01-01T00:00:00": return datetime(2018, 1, 1) elif s == "2018-12-31T23:59:59": return datetime(2018, 12, 31, 23, 59, 59) + elif s == "2022-01-01T00:00:00": + return datetime(2022, 1, 1) else: return None @@ -260,12 +264,30 @@ def test_datetime_eval() -> None: expected = datetime(2018, 9, 3, 0, 0, 0) assert result == expected + result = datetime_eval( + "holiday('Eid al-Fitr', datetime('2000-01-01T00:00:00'), 'SA')" + ) + expected = datetime(2000, 1, 8, 0, 0, 0) + assert result == expected + result = datetime_eval( "holiday('Boxing day', datetime('2018-01-01T00:00:00'), 'UK')" ) expected = datetime(2018, 12, 26, 0, 0, 0) assert result == expected + result = datetime_eval( + "holiday('Juneteenth', datetime('2022-01-01T00:00:00'), 'US')" + ) + expected = datetime(2022, 6, 19, 0, 0, 0) + assert result == expected + + result = datetime_eval( + "holiday('Independence Day', datetime('2022-01-01T00:00:00'), 'US')" + ) + expected = datetime(2022, 7, 4, 0, 0, 0) + assert result == expected + result = datetime_eval( "lastday(dateadd(datetime('2018-01-01T00:00:00'), 1, month), month)" )