templatetags: factorize formats parser for badges and opening hours (#50419)

This commit is contained in:
Nicolas Roche 2021-01-21 18:01:47 +01:00
parent 8e99bea02f
commit 116511fc31
1 changed files with 59 additions and 68 deletions

View File

@ -250,53 +250,41 @@ def parse_opening_hours_data(mairie_data):
yield (days_list, time_table)
def get_slots_from_mairie_format(data, base_datetime):
"""Process mairie json and return slots the opening hours in chronological order beginning today"""
def parse_mairie_formats(data, base_datetime, oh_add, ohs_add, ohs_del):
if 'properties' in data:
data = data['properties']
known_format = False
slots = []
exclusion_slots = []
previous_week = base_datetime - datetime.timedelta(7)
next_week = base_datetime + datetime.timedelta(7)
if len(data.get('openinghoursspecification', [])) > 0:
# prepare annual opening exclusions
for specification in data.get('openinghoursspecification', []):
valid_from, valid_through = previous_week, next_week
if specification.get('validFrom'):
valid_from = parse_valid_from(specification)
if specification.get('validThrough'):
valid_through = parse_valid_through(specification)
if not valid_from or not valid_through:
continue
if specification.get('opens') and specification.get('closes'):
# case when opening periods are defined
if valid_from <= base_datetime < valid_through:
known_format = True
try:
day_number, time_table = get_time_table_from_specification(specification)
except ValueError:
continue
timeslot = get_slot(day_number, time_table, base_datetime)
slots.append(timeslot)
else:
# case when exclusions are defined
exclusion_slots.append(TimeSlot(valid_from, valid_through))
for specification in data.get('openinghoursspecification', []):
valid_from, valid_through = previous_week, next_week
if specification.get('validFrom'):
valid_from = parse_valid_from(specification)
if specification.get('validThrough'):
valid_through = parse_valid_through(specification)
if not valid_from or not valid_through:
continue
if specification.get('opens') and specification.get('closes'):
known_format = True
# case when opening periods are defined
if valid_from <= base_datetime < valid_through:
# parse specification only for the current period relative to utcnow()
try:
day_number, time_table = get_time_table_from_specification(specification)
except ValueError:
continue
ohs_add(day_number, time_table)
else:
# case when exclusions are defined
ohs_del(valid_from, valid_through)
if not known_format and len(data.get('openinghours', [])) > 0:
if not known_format:
# some mairie may only have opening periods defined into openinghours (e.g. Bron)
for days_list, time_table in parse_opening_hours_data(data):
known_format = True
for weekday in days_list:
day_number = EN_ABBREV_WEEKDAYS_LIST.index(weekday)
timeslot = get_slot(day_number, time_table, base_datetime)
# add to slots the opening hours in chronological order beginning from today
slots.append(timeslot)
# order slots and cycle the list beginning with 'base_datetime'
slots.sort(key=operator.attrgetter('start'))
return (slots, exclusion_slots, known_format)
oh_add(days_list, time_table)
return known_format
def parse_valid_from(spec):
@ -318,14 +306,11 @@ def parse_valid_through(spec):
@register.simple_tag
def get_mairie_opening_hours(mairie_data):
"""Process Mairie Geojson to extract data of each day's opening hours"""
if not mairie_data:
return ''
if 'properties' in mairie_data:
mairie_data = mairie_data['properties']
base_datetime = now()
days_list = []
opening_hours_dict = OrderedDict(
zip(EN_ABBREV_WEEKDAYS_LIST, [{'am': None, 'pm': None} for i in range(7)])
)
@ -341,32 +326,18 @@ def get_mairie_opening_hours(mairie_data):
time_table['end_minute'],
)
known_format = False
previous_week = base_datetime - datetime.timedelta(7)
next_week = base_datetime + datetime.timedelta(7)
for specification in mairie_data.get('openinghoursspecification', []):
valid_from, valid_through = previous_week, next_week
if specification.get('validFrom'):
valid_from = parse_valid_from(specification)
if specification.get('validThrough'):
valid_through = parse_valid_through(specification)
if not valid_from or not valid_through:
continue
# case when opening periods are defined
if 'opens' in specification and 'closes' in specification:
known_format = True
# parse specification only for the current period relative to utcnow()
if valid_from < base_datetime < valid_through:
day_number, time_table = get_time_table_from_specification(specification)
weekday = EN_ABBREV_WEEKDAYS_LIST[day_number]
update_opening_hours(weekday, time_table)
def oh_add(days_list, time_table):
for weekday in days_list:
update_opening_hours(weekday, time_table)
if not known_format:
# some mairie may only have opening periods defined into openinghours (e.g. Bron)
for days_list, time_table in parse_opening_hours_data(mairie_data):
known_format = True
for weekday in days_list:
update_opening_hours(weekday, time_table)
def ohs_add(day_number, time_table):
weekday = EN_ABBREV_WEEKDAYS_LIST[day_number]
update_opening_hours(weekday, time_table)
def ohs_del(valid_from, valid_through):
pass
known_format = parse_mairie_formats(mairie_data, base_datetime, oh_add, ohs_add, ohs_del)
if not (
any([x['am'] for x in opening_hours_dict.values()])
@ -392,11 +363,31 @@ def as_opening_hours_badge(data):
return ''
base_datetime = now()
slots = []
exclusion_slots = []
today = base_datetime.date()
(slots, known_format) = get_slots_from_mdr_format(data, base_datetime)
def oh_add(days_list, time_table):
for weekday in days_list:
day_number = EN_ABBREV_WEEKDAYS_LIST.index(weekday)
timeslot = get_slot(day_number, time_table, base_datetime)
# add to slots the opening hours in chronological order beginning from today
slots.append(timeslot)
def ohs_add(day_number, time_table):
timeslot = get_slot(day_number, time_table, base_datetime)
slots.append(timeslot)
def ohs_del(valid_from, valid_through):
exclusion_slots.append(TimeSlot(valid_from, valid_through))
if not known_format:
(slots, exclusion_slots, known_format) = get_slots_from_mairie_format(data, base_datetime)
# Process mairie json and return slots the opening hours
# in chronological order beginning today
known_format = parse_mairie_formats(data, base_datetime, oh_add, ohs_add, ohs_del)
# order slots and cycle the list beginning with 'base_datetime'
slots.sort(key=operator.attrgetter('start'))
if not known_format:
return ''