# pylint: disable=missing-function-docstring """ Tests on opening hours helpers """ import datetime import pytest from mylib import opening_hours # # Test on parse_exceptional_closures() # def test_parse_exceptional_closures_one_day_without_time_period(): assert opening_hours.parse_exceptional_closures(["22/09/2017"]) == [ {"days": [datetime.date(2017, 9, 22)], "hours_periods": []} ] def test_parse_exceptional_closures_one_day_with_time_period(): assert opening_hours.parse_exceptional_closures(["26/11/2017 9h30-12h30"]) == [ { "days": [datetime.date(2017, 11, 26)], "hours_periods": [{"start": datetime.time(9, 30), "stop": datetime.time(12, 30)}], } ] def test_parse_exceptional_closures_one_day_with_multiple_time_periods(): assert opening_hours.parse_exceptional_closures(["26/11/2017 9h30-12h30 14h-18h"]) == [ { "days": [datetime.date(2017, 11, 26)], "hours_periods": [ {"start": datetime.time(9, 30), "stop": datetime.time(12, 30)}, {"start": datetime.time(14, 0), "stop": datetime.time(18, 0)}, ], } ] def test_parse_exceptional_closures_full_days_period(): assert opening_hours.parse_exceptional_closures(["20/09/2017-22/09/2017"]) == [ { "days": [ datetime.date(2017, 9, 20), datetime.date(2017, 9, 21), datetime.date(2017, 9, 22), ], "hours_periods": [], } ] def test_parse_exceptional_closures_invalid_days_period(): with pytest.raises(ValueError): opening_hours.parse_exceptional_closures(["22/09/2017-21/09/2017"]) def test_parse_exceptional_closures_days_period_with_time_period(): assert opening_hours.parse_exceptional_closures(["20/09/2017-22/09/2017 9h-12h"]) == [ { "days": [ datetime.date(2017, 9, 20), datetime.date(2017, 9, 21), datetime.date(2017, 9, 22), ], "hours_periods": [{"start": datetime.time(9, 0), "stop": datetime.time(12, 0)}], } ] def test_parse_exceptional_closures_time_period_without_days(): with pytest.raises(ValueError): opening_hours.parse_exceptional_closures(["9h-12h"]) def test_parse_exceptional_closures_invalid_time_period(): with pytest.raises(ValueError): opening_hours.parse_exceptional_closures(["20/09/2017 9h-8h"]) def test_parse_exceptional_closures_multiple_periods(): assert opening_hours.parse_exceptional_closures( ["20/09/2017 25/11/2017-26/11/2017 9h30-12h30 14h-18h"] ) == [ { "days": [ datetime.date(2017, 9, 20), datetime.date(2017, 11, 25), datetime.date(2017, 11, 26), ], "hours_periods": [ {"start": datetime.time(9, 30), "stop": datetime.time(12, 30)}, {"start": datetime.time(14, 0), "stop": datetime.time(18, 0)}, ], } ] # # Tests on parse_normal_opening_hours() # def test_parse_normal_opening_hours_one_day(): assert opening_hours.parse_normal_opening_hours(["jeudi"]) == [ {"days": ["jeudi"], "hours_periods": []} ] def test_parse_normal_opening_hours_multiple_days(): assert opening_hours.parse_normal_opening_hours(["lundi jeudi"]) == [ {"days": ["lundi", "jeudi"], "hours_periods": []} ] def test_parse_normal_opening_hours_invalid_day(): with pytest.raises(ValueError): opening_hours.parse_exceptional_closures(["invalid"]) def test_parse_normal_opening_hours_one_days_period(): assert opening_hours.parse_normal_opening_hours(["lundi-jeudi"]) == [ {"days": ["lundi", "mardi", "mercredi", "jeudi"], "hours_periods": []} ] def test_parse_normal_opening_hours_one_day_with_one_time_period(): assert opening_hours.parse_normal_opening_hours(["jeudi 9h-12h"]) == [ { "days": ["jeudi"], "hours_periods": [{"start": datetime.time(9, 0), "stop": datetime.time(12, 0)}], } ] def test_parse_normal_opening_hours_invalid_days_period(): with pytest.raises(ValueError): opening_hours.parse_normal_opening_hours(["jeudi-mardi"]) with pytest.raises(ValueError): opening_hours.parse_normal_opening_hours(["lundi-mardi-mercredi"]) def test_parse_normal_opening_hours_one_time_period(): assert opening_hours.parse_normal_opening_hours(["9h-18h30"]) == [ { "days": [], "hours_periods": [{"start": datetime.time(9, 0), "stop": datetime.time(18, 30)}], } ] def test_parse_normal_opening_hours_invalid_time_period(): with pytest.raises(ValueError): opening_hours.parse_normal_opening_hours(["12h-10h"]) def test_parse_normal_opening_hours_multiple_periods(): assert opening_hours.parse_normal_opening_hours( ["lundi-vendredi 9h30-12h30 14h-18h", "samedi 9h30-18h", "dimanche 9h30-12h"] ) == [ { "days": ["lundi", "mardi", "mercredi", "jeudi", "vendredi"], "hours_periods": [ {"start": datetime.time(9, 30), "stop": datetime.time(12, 30)}, {"start": datetime.time(14, 0), "stop": datetime.time(18, 0)}, ], }, { "days": ["samedi"], "hours_periods": [ {"start": datetime.time(9, 30), "stop": datetime.time(18, 0)}, ], }, { "days": ["dimanche"], "hours_periods": [ {"start": datetime.time(9, 30), "stop": datetime.time(12, 0)}, ], }, ] def test_parse_normal_opening_hours_is_sorted(): assert opening_hours.parse_normal_opening_hours( [ "samedi 9h30-18h", "lundi-vendredi 14h-18h 9h30-12h30", "samedi 9h30-12h", "dimanche 9h30-12h", ] ) == [ { "days": ["lundi", "mardi", "mercredi", "jeudi", "vendredi"], "hours_periods": [ {"start": datetime.time(9, 30), "stop": datetime.time(12, 30)}, {"start": datetime.time(14, 0), "stop": datetime.time(18, 0)}, ], }, { "days": ["samedi"], "hours_periods": [ {"start": datetime.time(9, 30), "stop": datetime.time(12, 0)}, ], }, { "days": ["samedi"], "hours_periods": [ {"start": datetime.time(9, 30), "stop": datetime.time(18, 0)}, ], }, { "days": ["dimanche"], "hours_periods": [ {"start": datetime.time(9, 30), "stop": datetime.time(12, 0)}, ], }, ] # # Tests on normal opening hours # normal_opening_hours = [ "lundi-mardi jeudi 9h30-12h30 14h-16h30", "mercredi vendredi 9h30-12h30 14h-17h", "samedi", ] normally_opened_datetime = datetime.datetime(2024, 3, 1, 10, 15) normally_opened_all_day_datetime = datetime.datetime(2024, 4, 6, 10, 15) normally_closed_datetime = datetime.datetime(2017, 3, 1, 20, 15) normally_closed_all_day_datetime = datetime.datetime(2024, 4, 7, 20, 15) def test_its_normally_open(): assert opening_hours.its_normally_open(normal_opening_hours, when=normally_opened_datetime) def test_its_normally_open_all_day(): assert opening_hours.its_normally_open( normal_opening_hours, when=normally_opened_all_day_datetime ) def test_its_normally_closed(): assert not opening_hours.its_normally_open(normal_opening_hours, when=normally_closed_datetime) def test_its_normally_closed_all_day(): assert not opening_hours.its_normally_open( normal_opening_hours, when=normally_closed_all_day_datetime ) def test_its_normally_open_ignore_time(): assert opening_hours.its_normally_open( normal_opening_hours, when=normally_closed_datetime.date(), ignore_time=True ) def test_its_normally_closed_ignore_time(): assert not opening_hours.its_normally_open( normal_opening_hours, when=normally_closed_all_day_datetime.date(), ignore_time=True ) # # Tests on non working days # nonworking_public_holidays = [ "1janvier", "paques", "lundi_paques", "8mai", "jeudi_ascension", "lundi_pentecote", "14juillet", "15aout", "1novembre", "11novembre", "noel", ] nonworking_date = datetime.date(2017, 1, 1) not_included_nonworking_date = datetime.date(2017, 5, 1) not_nonworking_date = datetime.date(2017, 5, 2) def test_its_nonworking_day(): assert ( opening_hours.its_nonworking_day(nonworking_public_holidays, date=nonworking_date) is True ) def test_its_not_nonworking_day(): assert ( opening_hours.its_nonworking_day( nonworking_public_holidays, date=not_nonworking_date, ) is False ) def test_its_not_included_nonworking_day(): assert ( opening_hours.its_nonworking_day( nonworking_public_holidays, date=not_included_nonworking_date, ) is False ) # # Tests in exceptional closures # exceptional_closures = [ "22/09/2017", "20/09/2017-22/09/2017", "20/09/2017-22/09/2017 18/09/2017", "25/11/2017", "26/11/2017 9h30-12h30", "27/11/2017 17h-18h 9h30-12h30", ] exceptional_closure_all_day_date = datetime.date(2017, 9, 22) exceptional_closure_all_day_datetime = datetime.datetime.combine( exceptional_closure_all_day_date, datetime.time(20, 15) ) exceptional_closure_datetime = datetime.datetime(2017, 11, 26, 10, 30) exceptional_closure_datetime_hours_period = { "start": datetime.time(9, 30), "stop": datetime.time(12, 30), } not_exceptional_closure_date = datetime.date(2019, 9, 22) def test_its_exceptionally_closed(): assert ( opening_hours.its_exceptionally_closed( exceptional_closures, when=exceptional_closure_all_day_datetime ) is True ) def test_its_not_exceptionally_closed(): assert ( opening_hours.its_exceptionally_closed( exceptional_closures, when=not_exceptional_closure_date ) is False ) def test_its_exceptionally_closed_all_day(): assert ( opening_hours.its_exceptionally_closed( exceptional_closures, when=exceptional_closure_all_day_datetime, all_day=True ) is True ) def test_its_not_exceptionally_closed_all_day(): assert ( opening_hours.its_exceptionally_closed( exceptional_closures, when=exceptional_closure_datetime, all_day=True ) is False ) def test_get_exceptional_closures_hours(): assert opening_hours.get_exceptional_closures_hours( exceptional_closures, date=exceptional_closure_datetime.date() ) == [exceptional_closure_datetime_hours_period] def test_get_exceptional_closures_hours_all_day(): assert opening_hours.get_exceptional_closures_hours( exceptional_closures, date=exceptional_closure_all_day_date ) == [{"start": datetime.datetime.min.time(), "stop": datetime.datetime.max.time()}] def test_get_exceptional_closures_hours_is_sorted(): assert opening_hours.get_exceptional_closures_hours( ["27/11/2017 17h-18h 9h30-12h30"], date=datetime.date(2017, 11, 27) ) == [ {"start": datetime.time(9, 30), "stop": datetime.time(12, 30)}, {"start": datetime.time(17, 0), "stop": datetime.time(18, 0)}, ] # # Tests on is_closed # def test_is_closed_when_normaly_closed_by_hour(): assert opening_hours.is_closed( normal_opening_hours_values=normal_opening_hours, exceptional_closures_values=exceptional_closures, nonworking_public_holidays_values=nonworking_public_holidays, when=datetime.datetime(2017, 5, 1, 20, 15), ) == {"closed": True, "exceptional_closure": False, "exceptional_closure_all_day": False} def test_is_closed_on_exceptional_closure_full_day(): assert opening_hours.is_closed( normal_opening_hours_values=normal_opening_hours, exceptional_closures_values=exceptional_closures, nonworking_public_holidays_values=nonworking_public_holidays, when=datetime.datetime(2017, 9, 22, 14, 15), ) == {"closed": True, "exceptional_closure": True, "exceptional_closure_all_day": True} def test_is_closed_on_exceptional_closure_day(): assert opening_hours.is_closed( normal_opening_hours_values=normal_opening_hours, exceptional_closures_values=exceptional_closures, nonworking_public_holidays_values=nonworking_public_holidays, when=datetime.datetime(2017, 11, 26, 10, 30), ) == {"closed": True, "exceptional_closure": True, "exceptional_closure_all_day": False} def test_is_closed_on_nonworking_public_holidays(): assert opening_hours.is_closed( normal_opening_hours_values=normal_opening_hours, exceptional_closures_values=exceptional_closures, nonworking_public_holidays_values=nonworking_public_holidays, when=datetime.datetime(2017, 1, 1, 10, 30), ) == {"closed": True, "exceptional_closure": False, "exceptional_closure_all_day": False} def test_is_closed_when_normaly_closed_by_day(): assert opening_hours.is_closed( normal_opening_hours_values=normal_opening_hours, exceptional_closures_values=exceptional_closures, nonworking_public_holidays_values=nonworking_public_holidays, when=datetime.datetime(2017, 5, 7, 14, 15), ) == {"closed": True, "exceptional_closure": False, "exceptional_closure_all_day": False} def test_is_closed_when_normaly_opened(): assert opening_hours.is_closed( normal_opening_hours_values=normal_opening_hours, exceptional_closures_values=exceptional_closures, nonworking_public_holidays_values=nonworking_public_holidays, when=datetime.datetime(2017, 5, 2, 15, 15), ) == {"closed": False, "exceptional_closure": False, "exceptional_closure_all_day": False} def test_easter_date(): assert opening_hours.easter_date(2010) == datetime.date(2010, 4, 4) assert opening_hours.easter_date(2011) == datetime.date(2011, 4, 24) assert opening_hours.easter_date(2012) == datetime.date(2012, 4, 8) assert opening_hours.easter_date(2013) == datetime.date(2013, 3, 31) assert opening_hours.easter_date(2014) == datetime.date(2014, 4, 20) assert opening_hours.easter_date(2015) == datetime.date(2015, 4, 5) assert opening_hours.easter_date(2016) == datetime.date(2016, 3, 27) assert opening_hours.easter_date(2017) == datetime.date(2017, 4, 16) assert opening_hours.easter_date(2018) == datetime.date(2018, 4, 1) assert opening_hours.easter_date(2019) == datetime.date(2019, 4, 21) assert opening_hours.easter_date(2020) == datetime.date(2020, 4, 12) assert opening_hours.easter_date(2021) == datetime.date(2021, 4, 4) def test_nonworking_french_public_days_of_the_year(): assert opening_hours.nonworking_french_public_days_of_the_year(2021) == { "1janvier": datetime.date(2021, 1, 1), "paques": datetime.date(2021, 4, 4), "lundi_paques": datetime.date(2021, 4, 5), "1mai": datetime.date(2021, 5, 1), "8mai": datetime.date(2021, 5, 8), "jeudi_ascension": datetime.date(2021, 5, 13), "pentecote": datetime.date(2021, 5, 23), "lundi_pentecote": datetime.date(2021, 5, 24), "14juillet": datetime.date(2021, 7, 14), "15aout": datetime.date(2021, 8, 15), "1novembre": datetime.date(2021, 11, 1), "11novembre": datetime.date(2021, 11, 11), "noel": datetime.date(2021, 12, 25), "saint_etienne": datetime.date(2021, 12, 26), } def test_next_opening_date(): assert opening_hours.next_opening_date( normal_opening_hours_values=normal_opening_hours, exceptional_closures_values=exceptional_closures, nonworking_public_holidays_values=nonworking_public_holidays, date=datetime.date(2021, 4, 4), ) == datetime.date(2021, 4, 6) def test_next_opening_hour(): assert opening_hours.next_opening_hour( normal_opening_hours_values=normal_opening_hours, exceptional_closures_values=exceptional_closures, nonworking_public_holidays_values=nonworking_public_holidays, when=datetime.datetime(2021, 4, 4, 10, 30), ) == datetime.datetime(2021, 4, 6, 9, 30) def test_next_opening_hour_with_exceptionnal_closure_hours(): assert opening_hours.next_opening_hour( normal_opening_hours_values=["lundi-vendredi 9h-12h 14h-18h"], exceptional_closures_values=["06/04/2021 9h-13h 14h-16h"], nonworking_public_holidays_values=nonworking_public_holidays, when=datetime.datetime(2021, 4, 4, 10, 30), ) == datetime.datetime(2021, 4, 6, 16, 0) def test_next_opening_hour_with_exceptionnal_closure_day(): assert opening_hours.next_opening_hour( normal_opening_hours_values=["lundi-vendredi 9h-12h 14h-18h"], exceptional_closures_values=["06/04/2021"], nonworking_public_holidays_values=nonworking_public_holidays, when=datetime.datetime(2021, 4, 4, 10, 30), ) == datetime.datetime(2021, 4, 7, 9, 0) def test_next_opening_hour_with_overlapsed_opening_hours(): assert opening_hours.next_opening_hour( normal_opening_hours_values=["lundi-vendredi 9h-12h 14h-18h", "mardi 8h-19h"], exceptional_closures_values=["06/04/2021 9h-13h 14h-16h"], nonworking_public_holidays_values=nonworking_public_holidays, when=datetime.datetime(2021, 4, 4, 10, 30), ) == datetime.datetime(2021, 4, 6, 8, 0) def test_next_opening_hour_with_too_large_exceptionnal_closure_days(): assert ( opening_hours.next_opening_hour( normal_opening_hours_values=["lundi-vendredi 9h-12h 14h-18h"], exceptional_closures_values=["06/04/2021-16-04/2021"], nonworking_public_holidays_values=nonworking_public_holidays, when=datetime.datetime(2021, 4, 4, 10, 30), max_anaylse_days=10, ) is False ) def test_next_opening_hour_on_opened_moment(): assert opening_hours.next_opening_hour( normal_opening_hours_values=["lundi-vendredi 9h-12h 14h-18h"], exceptional_closures_values=[], nonworking_public_holidays_values=nonworking_public_holidays, when=datetime.datetime(2021, 4, 6, 10, 30), ) == datetime.datetime(2021, 4, 6, 10, 30) def test_next_opening_hour_on_same_day(): assert opening_hours.next_opening_hour( normal_opening_hours_values=["lundi-vendredi 9h-12h 14h-18h"], exceptional_closures_values=[], nonworking_public_holidays_values=nonworking_public_holidays, when=datetime.datetime(2021, 4, 6, 13, 0), ) == datetime.datetime(2021, 4, 6, 14, 0) assert opening_hours.next_opening_hour( normal_opening_hours_values=["lundi-vendredi 9h-12h 14h-18h"], exceptional_closures_values=[], nonworking_public_holidays_values=nonworking_public_holidays, when=datetime.datetime(2021, 4, 6, 16, 0), ) == datetime.datetime(2021, 4, 6, 16, 0) assert opening_hours.next_opening_hour( normal_opening_hours_values=["lundi-vendredi"], exceptional_closures_values=[], nonworking_public_holidays_values=nonworking_public_holidays, when=datetime.datetime(2021, 4, 6, 16, 0), ) == datetime.datetime(2021, 4, 6, 16, 0) def test_next_opening_hour_on_opened_day_but_too_late(): assert opening_hours.next_opening_hour( normal_opening_hours_values=["lundi-vendredi 9h-12h 14h-18h"], exceptional_closures_values=[], nonworking_public_holidays_values=nonworking_public_holidays, when=datetime.datetime(2021, 4, 6, 23, 0), ) == datetime.datetime(2021, 4, 7, 9, 0) def test_previous_opening_date(): assert opening_hours.previous_opening_date( normal_opening_hours_values=["lundi-vendredi 9h-18h"], exceptional_closures_values=[], nonworking_public_holidays_values=nonworking_public_holidays, date=datetime.date(2024, 4, 1), ) == datetime.date(2024, 3, 29) def test_previous_opening_hour(): assert opening_hours.previous_opening_hour( normal_opening_hours_values=["lundi-vendredi 9h-18h"], exceptional_closures_values=[], nonworking_public_holidays_values=nonworking_public_holidays, when=datetime.datetime(2024, 4, 1, 10, 30), ) == datetime.datetime(2024, 3, 29, 18, 0) def test_previous_opening_hour_with_exceptionnal_closure_hours(): assert opening_hours.previous_opening_hour( normal_opening_hours_values=["lundi-vendredi 9h-12h 14h-18h"], exceptional_closures_values=["29/03/2024 14h-18h"], nonworking_public_holidays_values=nonworking_public_holidays, when=datetime.datetime(2024, 4, 1, 10, 30), ) == datetime.datetime(2024, 3, 29, 12, 0) assert opening_hours.previous_opening_hour( normal_opening_hours_values=["lundi-vendredi 9h-12h 14h-18h"], exceptional_closures_values=["29/03/2024 16h-18h"], nonworking_public_holidays_values=nonworking_public_holidays, when=datetime.datetime(2024, 4, 1, 10, 30), ) == datetime.datetime(2024, 3, 29, 16, 0) def test_previous_opening_hour_with_exceptionnal_closure_day(): assert opening_hours.previous_opening_hour( normal_opening_hours_values=["lundi-vendredi 9h-12h 14h-18h"], exceptional_closures_values=["29/03/2024"], nonworking_public_holidays_values=nonworking_public_holidays, when=datetime.datetime(2024, 4, 1, 10, 30), ) == datetime.datetime(2024, 3, 28, 18, 0) def test_previous_opening_hour_with_overlapsed_opening_hours(): assert opening_hours.previous_opening_hour( normal_opening_hours_values=["lundi-vendredi 9h-12h 14h-18h", "mardi 8h-19h"], exceptional_closures_values=[], nonworking_public_holidays_values=nonworking_public_holidays, when=datetime.datetime(2024, 4, 3, 8, 30), ) == datetime.datetime(2024, 4, 2, 19, 0) def test_previous_opening_hour_with_too_large_exceptionnal_closure_days(): assert ( opening_hours.previous_opening_hour( normal_opening_hours_values=["lundi-vendredi 9h-12h 14h-18h"], exceptional_closures_values=["06/03/2024-16-04/2024"], nonworking_public_holidays_values=nonworking_public_holidays, when=datetime.datetime(2024, 4, 17, 8, 30), max_anaylse_days=10, ) is False ) def test_previous_opening_hour_on_opened_moment(): assert opening_hours.previous_opening_hour( normal_opening_hours_values=["lundi-vendredi 9h-12h 14h-18h"], exceptional_closures_values=[], nonworking_public_holidays_values=nonworking_public_holidays, when=datetime.datetime(2024, 4, 5, 10, 30), ) == datetime.datetime(2024, 4, 5, 10, 30) def test_previous_opening_hour_on_same_day(): assert opening_hours.previous_opening_hour( normal_opening_hours_values=["lundi-vendredi 9h-12h 14h-18h"], exceptional_closures_values=[], nonworking_public_holidays_values=nonworking_public_holidays, when=datetime.datetime(2024, 4, 5, 13, 0), ) == datetime.datetime(2024, 4, 5, 12, 0) assert opening_hours.previous_opening_hour( normal_opening_hours_values=["lundi-vendredi 9h-12h 14h-18h"], exceptional_closures_values=[], nonworking_public_holidays_values=nonworking_public_holidays, when=datetime.datetime(2024, 4, 5, 16, 0), ) == datetime.datetime(2024, 4, 5, 16, 0) assert opening_hours.previous_opening_hour( normal_opening_hours_values=["lundi-vendredi"], exceptional_closures_values=[], nonworking_public_holidays_values=nonworking_public_holidays, when=datetime.datetime(2024, 4, 5, 16, 0), ) == datetime.datetime(2024, 4, 5, 16, 0) def test_previous_opening_hour_on_opened_day_but_too_early(): assert opening_hours.previous_opening_hour( normal_opening_hours_values=["lundi-vendredi 9h-12h 14h-18h"], exceptional_closures_values=[], nonworking_public_holidays_values=nonworking_public_holidays, when=datetime.datetime(2024, 4, 5, 8, 0), ) == datetime.datetime(2024, 4, 4, 18, 0)