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